是否有任何理由说明为什么使用std :: tuple传递c ++模板包

W.F*_*.F. 2 c++ templates tuples variadic-templates c++14

假设我们想要创建一个帮助类来反转模板包,例如如下:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用例如函数签名作为模板参数成功完成相同的事情:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我的经验std::tuple(例如此处)显示其旨在存储数据而不是在模板之间传递类型包.那么使用元组操作可变参数有什么实际的理由吗?

Bar*_*rry 7

那么使用a tuple来操作可变参数有什么实际的理由吗?

A tuple不会对其参数执行任何转换 - tuple<int[2]>确实包含一个int[2]作为其第一个类型,而a void(int[2])实际上是一个void(int*).同样适用于const经历衰变的功能和其他类型.这使得功能成为一种不可行的选择.

如果你写你自己的类型串(例如template <class... Ts> struct typelist{};),你仍然要重新实现 std::get,std::tuple_elementstd::tuple_size.这是件好事tuple- 它准备好了,很有用.

每个人都已经知道是什么了std::tuple.即使函数签名没有以一种破坏的方式衰减它们的参数,我仍然会使用所创建的类型作为类型的异构容器 - 而不是将你的解决方案塞进其他恰好工作的东西.最不惊讶的原则和所有.

  • 但缺点是:`std :: tuple`的重量非常大,创建几十或几百个实例可能会让编译时间陷入困境. (3认同)