Registration.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include "Utilities/TMPL.hpp"
7 
8 /// \ingroup UtilitiesGroup
9 /// \brief Helpers for derived class registration
10 ///
11 /// SpECTRE's factory mechanism requires that the base class contain a
12 /// list of all derived classes (in the special nested type alias
13 /// `creatable_classes`). This can be problematic when the desired
14 /// list of derived classes can vary with use of the base class.
15 /// These helpers provide a method to simplify handling these
16 /// compile-time registrations.
17 ///
18 /// Each optional derived class defines a registrar helper and both
19 /// the base class and derived classes are templated on the list of
20 /// registrars. The typical structure of these classes is:
21 /// \snippet Test_Registration.cpp registrar_structure
22 /// A concrete base class type with a specific set of derived classes
23 /// is constructed like
24 /// \snippet Test_Registration.cpp registrar_use
25 ///
26 /// It is frequently useful to default the registrar list in a derived
27 /// class to the registrar for that class. This ensures that any
28 /// methods in the base class using the registrar list (such as those
29 /// using `DEFINE_FAKE_VIRTUAL()` or `call_with_dynamic_type()`) work
30 /// as expected on an explicitly constructed derived class with the
31 /// list omitted.
32 namespace Registration {
33 /// A template for defining a registrar.
34 ///
35 /// A registrar for a class can be defined by making a type alias to
36 /// this struct, filling in the registrant.
37 /// \snippet Test_Registration.cpp registrar
38 /// In more complex cases (such as with non-type template
39 /// parameters) defining a registrar manually may be necessary.
40 /// \snippet Test_Registration.cpp custom_registrar
41 template <template <typename...> class Registrant, typename... Args>
42 struct Registrar {
43  // Final registrant type, specialized with input Args... and the
44  // RegistrarList it was extracted from. This will be a full
45  // specialization of a derived class that uses the registration
46  // framework.
47  template <typename RegistrarList>
48  using f = Registrant<Args..., RegistrarList>;
49 };
50 
51 namespace detail {
52 template <typename RegistrarList, typename Registrar>
53 struct registrant {
54  using type = typename Registrar::template f<RegistrarList>;
55 };
56 } // namespace detail
57 
58 /// Transform a list of registrars into the list of associated
59 /// registrants. This is usually used to define the
60 /// `creatable_classes` type list.
61 template <typename RegistrarList>
62 using registrants = tmpl::transform<
63  tmpl::remove_duplicates<RegistrarList>,
64  detail::registrant<tmpl::pin<tmpl::remove_duplicates<RegistrarList>>,
65  tmpl::_1>>;
66 } // namespace Registration
tmpl::transform< tmpl::remove_duplicates< RegistrarList >, detail::registrant< tmpl::pin< tmpl::remove_duplicates< RegistrarList > >, tmpl::_1 > > registrants
Transform a list of registrars into the list of associated registrants. This is usually used to defin...
Definition: Registration.hpp:65
Definition: Determinant.hpp:11
Helpers for derived class registration.
Definition: Registration.hpp:32
A template for defining a registrar.
Definition: Registration.hpp:42
Wraps the template metaprogramming library used (brigand)