Are there any reasons why C ++ template packages are passed using std :: tuple

Suppose we want to create a helper class for a reverse package template, for example. in the following way:

#include <tuple> #include <utility> #include <typeinfo> #include <iostream> template <class> struct sizer; template <template<class...> class Pack, class... Args> struct sizer<Pack<Args...>> { static constexpr size_t value = sizeof...(Args); }; template <class Pack, class Indices = std::make_index_sequence<sizer<Pack>::value>> struct reverse_pack; template <class... Args, size_t... I> struct reverse_pack<std::tuple<Args...>, std::integer_sequence<std::size_t, I...>> { using type = typename std::tuple<typename std::tuple_element<(sizeof...(Args) - I - 1), std::tuple<Args...>>::type...>; }; int main() { std::cout << typeid(reverse_pack<std::tuple<int, float, double>>::type).name() << std::endl; } 

We could successfully do the same, using, for example, as a template parameter:

 #include <utility> #include <typeinfo> #include <iostream> template <class> struct sizer; template <class... Args> struct sizer<void(Args...)> { static constexpr size_t value = sizeof...(Args); }; template <size_t N, class Sign> struct nth_param; template <size_t N, class First, class... Args> struct nth_param<N, void(First, Args...)>: nth_param<N-1, void(Args...)> { }; template <class First, class... Args> struct nth_param<0, void(First, Args...)> { using type = First; }; template <class Pack, class Indices = std::make_index_sequence<sizer<Pack>::value>> struct reverse_pack; template <class... Args, size_t... I> struct reverse_pack<void(Args...), std::integer_sequence<std::size_t, I...>> { using type = void(typename nth_param<(sizeof...(Args) - I - 1), void(Args...)>::type...); }; int main() { std::cout << typeid(reverse_pack<void(int, float, double)>::type).name() << std::endl; } 

My experience with std::tuple (for example, here ) shows that it is designed to store data, and not to transfer type packets between templates. So, are there any practical reasons to use a tuple to work with variators?

+2
source share
1 answer

So, are there any practical reasons to use tuple to work with CVTs?

A tuple does not perform any conversion in its arguments. a tuple<int[2]> really contains int[2] as its first type, whereas void(int[2]) really void(int*) . The same is true for const , functions, and other types that undergo decay. This makes the function unviable.

If you wrote your own type list (for example, template <class... Ts> struct typelist{}; ), you still have to override std::get , std::tuple_element and std::tuple_size . This is a good thing about tuple - it is ready and helpful.

And everyone already knows what std::tuple . Even if the function signatures did not destroy their arguments in such a way that it would break, I would still use a type created as a heterogeneous container of types - and not customize your solution to something else that could happen. The principle of least surprise and all.

+7
source

All Articles