LILAC
|
Class for constructing statically-typed classes when type is determined at runtime. More...
#include <type_constructor.hpp>
Classes | |
class | _ttype |
This is an internal polymorphic base class. It returns a pointer of type tout. More... | |
class | ttype |
This is the actual creator class. It creates a pointer of Tin with the template parameter Tval. More... |
Public Types | |
typedef typelist< comp, double, float, example_type > | std_type_list |
Static Public Member Functions | |
template<class Tout , class = typename std::enable_if<std::is_base_of<vartype, Tout>::value >::type> | |
static void | create (std::shared_ptr< Tout > *in, const vartype *tval) |
Creates a Tout* pointing to a Tin<type>*, where type is the type of the vartype tval. | |
template<class Tl , class Tout , class = typename std::enable_if<std::is_base_of<vartype, Tout>::value >::type, class = typename std::enable_if<std::is_base_of<blacklist_checker, Tl>::value >::type> | |
static void | create (std::shared_ptr< Tout > *in, const vartype *tval) |
template<class Tout > | |
static std::shared_ptr< Tout > | create (const vartype *tval) |
Version of create that requires more template parameters, but directly returns a value. | |
template<class Tl , class Tout > | |
static std::shared_ptr< Tout > | create (const vartype *tval, const Tl blist) |
shortened version of blacklist function |
Class for constructing statically-typed classes when type is determined at runtime.
This engine faces two issues-the numerical type (complex, double, float) is decided at runtime. This problem is fairly simple to solve with runtime polymorphism-a base numerical class that makes virtual calls out to add, multiply, etc functions
However, all of the functions need to be instantiated at compile time, to ensure optimal performance. A solution based on runtime polymorphism would be unacceptably slow, probably by orders of magnitude
To get past this, a type-independent class can hold a pointer to a template class, where this class is selected at runtime. This hides the type-dependent functionality from the rest of the program.
There is still one problem, which is instantiating this template class. Currently, this can just be with a series of if statements:
This works, but has two big problems. We must statically list the types that can be transformed to in every location where this occurs. This is a headache, and prone to different lists in various places of code. Imagine creating a new type, and having to trawl the entire codebase editing this list
However, we can create a type constructor. This means that it takes a concrete type at runtime, such as complex, double, etc and returns a new concrete type such as a rk45 integrator of type complex, or double.
With templates, we can implement that in C++ as well, and as a bonus for arbitrary template and base classes as long as they inherit from one another, and as long as they inherit from vartype.
For example, say you want to initiate an rk45 integrator to the same type as an rhs functions.
You have a base class rk45, which represents the family of rk45 integrators and is the polymorphic base class
You also have a template class rk45_tmpl<T>, which is a template class inheriting from rk45 and actually implementing the integrator routines for type T.
Your function also has access to the right hand side being integrated, but only knows about the type information at runtime. Say that the type of ths rhs is T. To get a pointer to an rk45_tmpl<T> at runtime (in the form of an rk45*), you only have to make a single function call.
You can do either:
You can also pass your own non-standard list of types to check, allowing for specialized routines that don't need to operate on the standard numerical types
Tin | the template class that is being instaniated |
Definition at line 161 of file type_constructor.hpp.
typedef typelist<comp, double, float, example_type> type_constructor< Tin >::std_type_list |
This defines the standard allowed types. Simply add your own type to the list if it plays nicely with all the standard integrators. This means that it supports basic arithmetic operations with itself and doubles, and has an abs function (absolute value) definied in the global namespace
Definition at line 187 of file type_constructor.hpp.
|
inlinestatic |
Creates a Tout* pointing to a Tin<type>*, where type is the type of the vartype tval.
This function is the core of the type constructor. If the type of the parameter tval is type, then it returns a Tin<type>* casted up to a Tout. Notice that all instances of Tin must be able to be casted up to a Tout. This is also only useful if the needed functionality is polymorphic.
This version of the function is nice because it doesn't require that the user specify a second template parameter, namely the Tout parameter.
Supported types are currently: comp, double, long double, and float. To add your own, simply add another type to the typedef std_type_list. To prevent a type from being created, pass a blacklist
Definition at line 206 of file type_constructor.hpp.
|
inlinestatic |
|
inlinestatic |
Version of create that requires more template parameters, but directly returns a value.
Definition at line 233 of file type_constructor.hpp.
|
inlinestatic |
shortened version of blacklist function
Definition at line 240 of file type_constructor.hpp.