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