Derived class discovery at compile time¶
The RuntimeSelectionFactory
class is a template class that allows to register derived classes for creation at runtime via a factory class by its name.
This mechanism is similar to OpenFOAM’s runtime selection mechanism.
The classes are registered at compile time via static member initialization.
Additional explanation can be found in the following two posts on Stack OverFlow: Derived class discovery at compile time and How to automatically register a class on creation .
This approach allows to create a plugin architecture where a derived class can be loaded at runtime. Additionally, it simplifies the runtime selection of a specific class. The derived classes can be created by providing its name, as shown below:
std::unique_ptr<baseClass> derivedClass =
baseClass::create("Name of derivedClass", "Additional arguments",...);
The RuntimeSelectionFactory
class is a template class that manages the registration of the derived classes and stores the map of the registered classes.
The map associates a function with a string that is used to create the derived class.
Further details RuntimeSelectionFactory.
Usage¶
The following example shows how to use the RuntimeSelectionFactory
and RuntimeSelectionFactory::Register
to automatically register derived classes. (check registerClass.cpp
for details).
The static function create
returns a std::unique_ptr
to its base class and takes an argument list specified inside the template class NeoFOAM::Parameters<>
.
template<typename Base, typename... Args>
class RuntimeSelectionFactory<Base, Parameters<Args...>> : public RegisterDocumentation<Base>
{
static std::unique_ptr<Base> create(const std::string& key, Args... args)
{
keyExistsOrError(key);
auto ptr = table().at(key)(std::forward<Args>(args)...);
return ptr;
}
};
To register a class, derive from the BaseClass::Register class and pass the derived class as a template argument.
The derived class must implement the static functions name
, doc
, and schema
.
class DerivedClass : public BaseClass::Register<DerivedClass>
{
public:
DerivedClass() {}
static std::string name() { return "DerivedClass"; }
static std::string doc() { return "DerivedClass documentation"; }
static std::string schema() { return "DerivedClass schema"; }
};
After the classes have been defined, the create
function can be used to instantiate the derived classes based on the name provided.
std::unique_ptr<BaseClass> testDerived = BaseClass::create("DerivedClass");
All base classes are also registered in the NeoFOAM::BaseClassDocumentation
map and the documentation and the schema retrieved as followed:
std::string baseClassName = "BaseClass";
std::string derivedClass = "DerivedClass";
NeoFOAM::BaseClassDocumentation::doc(baseClassName, derivedClass)
NeoFOAM::BaseClassDocumentation::schema(baseClassName, derivedClass)
This mechanism should simplify the creation of tooling around NeoFOAM