How to restore a parameter package from TypeList

I have a variational template list:

template <class... Types> struct typelist {}; 

Then, how can I pass it to external code waiting for a package of parameters, for example std::tuple . In other words, I need to save the parameter package as a member or typedef in my type list, e.g.

 ... struct typelist { using types = Types; // Imaginary syntax } 

However, this is rejected by the compiler, saying that the types are unexpanded.

Any workaround?

This question is mentioned differently in the comments on this question , but was not covered by the existing answer.


Details requested in comments:

If I compile (-std = C ++ 17):

 template <class... T> struct typelist {}; std::tuple<typelist<int, int>> tp{0,1}; 

g ++ gives error: no matching function for call to 'std::tuple<typelist<int, int> >::tuple(<brace-enclosed initializer list>)' std::tuple<typelist<int, int>> tp{0,1};

If I compile (-std = C ++ 17):

 template <class... T> struct typelist { using types = T; }; 

g++ gives error: parameter packs not expanded with '...': using types = T;

+5
source share
2 answers

You need a little template to get the right tuple specialization from typelist , because you cannot just save the parameter package as it is.
As an example, you can do this by correctly using the function declaration and declaration of use:

 #include<tuple> #include<utility> #include<type_traits> template <class... T> struct typelist {}; template<typename... T> std::tuple<T...> foo(typelist<T...>); template<typename L> using tupleFromTypelist = decltype(foo(std::declval<L>())); int main() { using tl = typelist<int, int>; tupleFromTypelist<tl> tp{0,1}; static_assert(std::is_same<tupleFromTypelist<tl>, std::tuple<int, int>>::value, "!"); } 

Or a helper class similar to the one in the following example:

 #include<tuple> #include<utility> #include<type_traits> template <class... T> struct typelist {}; template<typename> struct helper; template<typename... T> struct helper<typelist<T...>> { using type = std::tuple<T...>; }; int main() { using tl = typelist<int, int>; helper<tl>::type tp{0,1}; static_assert(std::is_same<helper<tl>::type, std::tuple<int, int>>::value, "!"); } 

Otherwise, let the typelist expose the specialization tuple and get it directly from it:

 #include<tuple> #include<utility> #include<type_traits> template <class... T> struct typelist { using tuple = std::tuple<T...>; }; int main() { using tl = typelist<int, int>; tl::tuple tp{0,1}; static_assert(std::is_same<tl::tuple, std::tuple<int, int>>::value, "!"); } 

If this is the only type for which you want to use the parameter package, this is the easiest approach.

+4
source

You cannot save a parameter package in a type alias. You need to use the output of the template argument to extract the arguments of your type_list for reuse. One way is to use such a dummy function:

 template <typename... Args> struct type_list {}; template <typename... Args> std::tuple<Args...> to_tuple(type_list<Args...>); template <typename TypeList> struct type_list_to_tuple { using type = decltype(to_tuple(std::declval<TypeList>())); }; template <typename TypeList> using type_list_to_tuple_t = typename type_list_to_tuple<TypeList>::type; int main() { using my_type_list = type_list<int, float>; using my_tuple = type_list_to_tuple_t<my_type_list>; static_assert(std::is_same_v<my_tuple, std::tuple<int, float>>); } 
+2
source

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


All Articles