Yes, you can do this with recursion ... in fact, you are more or less reimplementing std::tuple
(and implicitly std::get
).
Hard work comes to access the members, since you cannot call them var1
, var2
, etc. unless you name them manually.
template <typename... TypeList> struct foo; template <typename Head, typename... Tail> struct foo<Head, Tail...>: public foo<Tail...> { Head var; };
I used inheritance here, but composition (using the foo<Tail...> tail
member) also works.
Now, if your types are unique, you can access the element by type ...
// this overload if VarType is the first template <typename VarType, typename... FooTail> VarType& foo_get(foo<VarType, FooTail...>& f) { return f.var; } // this overload to walk down to foo parent template <typename VarType, typename FooHead, typename... FooTail> VarType& foo_get(foo<FooHead, FooTail...>& foo) { return foo_get<VarType>(static_cast<foo<FooTail...>>(f)); } // call like: // int &x = foo_get<int>(my_foo_object);
or you can access by position:
template <int N, typename... TypeList> struct GetHelper; template <typename Head, typename... Tail> struct GetHelper<0, Head, Tail...> { static Head& get(foo<Head, Tail...> &f) { return f.var; } }; template <int N, typename Head, typename... Tail> struct GetHelper<N, Head, Tail...>: public GetHelper<N-1, Tail...> {}; template <int N, typename... TypeList> auto foo_get(foo<TypeList...> &f) -> GetHelper<N, TypeList...>::get(*static_cast<foo<TypeList...>*>(0)) { return GetHelper<N, TypeList...>::get(f) }
both of them can be improved to improve the error message (and although I used both methods, I did not even try to compile this sample code)