How to get a specific type from a package with a variational type?

I want to do something like this:

template<typename ...T> struct foo { bar<0 /*to index through types in pack*/ ,T...>::type var1; bar<1 /*to index through types in pack*/ ,T...>::type var2; ... } 

But how to define bar ? This does not require a recursion technique.

I need a common technique so that I can typedef any particular type from the type package, and not just the two shown in the example.

+6
source share
4 answers
 #include <iostream> #include <typeinfo> template<class T, class T2, class... Args> class C { public: typedef T type1; typedef T2 type2; }; int main() { typedef C<int, double, int, float> c; std::cout << typeid(c::type1).name() << " " << typeid(c::type2).name() << std::endl; } 

or mb something like this.

 #include <iostream> #include <typeinfo> template<int N, class T, class... Args> struct expand { public: typedef typename expand<N - 1, Args...>::type type; }; template<class T, class... Args> struct expand<1, T, Args...> { public: typedef T type; }; template<class... Args> class argsExpander { public: typedef typename expand<1, Args...>::type type1; typedef typename expand<2, Args...>::type type2; }; template<class... Args> class C { public: typename argsExpander<Args...>::type1 var1; typename argsExpander<Args...>::type2 var2; }; int main() { C<int, double, int, float> c; std::cout << typeid(c.var1).name() << " " << typeid(c.var2).name() << std::endl; } 

http://liveworkspace.org/code/7de289f128e86eb6006f576cbaf98991

+5
source

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) } // call like: // int &x = foo_get<2>(my_foo_object); 

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)

+1
source

If I understand your question correctly, you want to implement something similar to std :: tuple:

I think the tuple is implemented as follows:

 template <class T> class tuple { T mem; }; template <class T, class... REST> class tuple : tuple<REST...> { T mem; }; 
+1
source

Just use std :: tuple as @Xeo continues to comment. This is convenient and does exactly what you are trying to do.

Quote:

Why not just use std::tuple<T...> ?

Access elements like std::get<I>(tup) and

like std::tuple_element<I, std::tuple<T...>>::type

+1
source

Source: https://habr.com/ru/post/920408/


All Articles