Line data Source code
1 0 : // 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 `call_with_dynamic_type()`) work
30 : /// as expected on an explicitly constructed derived class with the
31 : /// list omitted.
32 1 : 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 1 : 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 0 : 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 1 : using registrants = tmpl::transform<
63 : tmpl::remove_duplicates<RegistrarList>,
64 : detail::registrant<tmpl::pin<tmpl::remove_duplicates<RegistrarList>>,
65 : tmpl::_1>>;
66 : } // namespace Registration
|