Classes | Typedefs
Registration Namespace Reference

Helpers for derived class registration. More...

Classes

struct  Registrar
 A template for defining a registrar. More...
 

Typedefs

template<typename RegistrarList >
using registrants = tmpl::transform< tmpl::remove_duplicates< RegistrarList >, detail::registrant< tmpl::pin< tmpl::remove_duplicates< RegistrarList > >, tmpl::_1 > >
 Transform a list of registrars into the list of associated registrants. This is usually used to define the creatable_classes type list.
 

Detailed Description

Helpers for derived class registration.

SpECTRE's factory mechanism requires that the base class contain a list of all derived classes (in the special nested type alias creatable_classes). This can be problematic when the desired list of derived classes can vary with use of the base class. These helpers provide a method to simplify handling these compile-time registrations.

Each optional derived class defines a registrar helper and both the base class and derived classes are templated on the list of registrars. The typical structure of these classes is:

template <typename Registrars>
class Base {
public:
Base() = default;
Base(const Base&) = default;
Base(Base&&) = default;
Base& operator=(const Base&) = default;
Base& operator=(Base&&) = default;
virtual ~Base() = default;
using creatable_classes = Registration::registrants<Registrars>;
virtual int func() const noexcept = 0;
};
template <typename Registrars>
class Derived1;
namespace Registrars {
} // namespace Registrars
template <typename Registrars = tmpl::list<Registrars::Derived1>>
class Derived1 : public Base<Registrars> {
public:
static constexpr OptionString help = "help";
using options = tmpl::list<>;
int func() const noexcept override { return 1; }
};

A concrete base class type with a specific set of derived classes is constructed like

using ConcreteBase =
Base<tmpl::list<Registrars::Derived1, Registrars::Derived2<double>,
Registrars::Derived3<4>>>;

It is frequently useful to default the registrar list in a derived class to the registrar for that class. This ensures that any methods in the base class using the registrar list (such as those using DEFINE_FAKE_VIRTUAL() or call_with_dynamic_type()) work as expected on an explicitly constructed derived class with the list omitted.