I'm very new to meta-programming and I'm experimenting with some examples.
I've designed a variadic template class as follows:
template <typename TA, typename... TB>
class A
[...]
This could be instantiated simply by passing different types like
A<Class1, Class2, Class3> * a = &(A<Class1, Class2, Class3>::instance());
where the pack TB only contains Class2
and Class3
.
Now, what I would like to achieve is to define in my header file a list of default types and build it gradually using #ifdef
definitions. I'll make an example
// concept of list of types
template<class... Ts>
struct typelist{};
// concatenating two typelists
template<class... Ts, class... Us>
auto concat(typelist<Ts...>, typelist<Us...>) -> typelist<Ts..., Us...>;
static typelist<> defaultTypelist;
#ifdef MACRO1
defaultTypelist = concat(defaultTypelist, typelist<Class2>);
// or something like defaultTypelist.push_front(Class2);
#endif
#ifdef MACRO2
defaultTypelist = concat(defaultTypelist, typelist<Class3>);
// or something like defaultTypelist.push_front(Class3);
#endif
By doing that, in my main I would like to instantiate my object as follows:
A<Class1, defaultTypelist> * a = &(A<Class1, defaultTypelist>::instance());
The main problem I see here is that I'm not able to gradually append types to defaultTypelist
since it was declared in the beginning at empty template typelist<>
. The compiler also returns an error if I try to pass an empty typelist as second parameter.
This may be trivial but so far I was not able to solve this, mainly because, as a beginner in meta-programming, compiler errors are not very helpful to me.
For this project, I have to use C++14 and below.
Big fat warning: don't do this.
The reason I'm saying, it'll change during the code. As you gradually add types, you'll end up defaultTypeList
having multiple meanings in different places of the code.
That said... Can it be done? Of course,
#define DEFAULT_TYPE_LIST typelist<>()
// ...
#ifdef MACRO1
static constexpr auto macro1_prev_dtl = DEFAULT_TYPE_LIST;
#undef DEFAULT_TYPE_LIST
#define DEFAULT_TYPE_LIST concat(macro1_prev_dtl, typelist<Class2>())
#endif
// ...
#ifdef MACRO2
static constexpr auto macro2_prev_dtl = DEFAULT_TYPE_LIST;
#undef DEFAULT_TYPE_LIST
#define DEFAULT_TYPE_LIST concat(macro2_prev_dtl, typelist<Class3>())
#endif
... then use DEFAULT_TYPE_LIST
wherever you'd like to access the current state of the list.