C++ 是否有任何原因导致c++;使用std::tuple传递模板包
假设我们要创建一个帮助器类来反转模板包,例如:C++ 是否有任何原因导致c++;使用std::tuple传递模板包,c++,templates,tuples,c++14,variadic-templates,C++,Templates,Tuples,C++14,Variadic Templates,假设我们要创建一个帮助器类来反转模板包,例如: #include <tuple> #include <utility> #include <typeinfo> #include <iostream> template <class> struct sizer; template <template<class...> class Pack, class... Args> struct sizer<Pac
#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;
}
#包括
#包括
#包括
#包括
模板
结构施胶器;
模板
结构筛
那么使用tuple
对变量进行操作有什么实际原因吗
tuple
不会对其参数执行任何转换,-tuple
确实包含一个int[2]
作为其第一个类型,而void(int[2])
实际上是一个void(int*)
。const
、函数和其他经历衰减的类型也是如此。这使得功能成为不可行的选择
如果您编写了自己的类型列表(例如template struct typelist{};
),您仍然需要重新实现std::get
、std::tuple\u元素
、和std::tuple\u size
。这正是tuple的好处所在,它随时可用
每个人都知道什么是std::tuple
。即使函数签名没有以破坏的方式衰减它们的参数,我仍然会使用创建为异构类型容器的类型,而不是将您的解决方案硬塞进其他碰巧工作的东西中。最小意外原则。浏览两个代码示例可以显示长度缩短,因为不必重新创建tuple\u元素。
函数参数类型可能不是数组,而tuple元素类型可能是数组。函数签名是错误的选择。它会调整其参数,例如,函数被调整为函数指针,常量被删除等。您还会使用什么struct
、class
和union
不允许您检查其中的类型和数量。有时可以使用对
,但这实际上是一个专门的元组
。开发人员倾向于使用std::tuple
,因为它附带了一些现成的工具,如tuple\u元素
。但是,缺点很大:std::tuple
非常重,创建几十个或100个实例确实会使编译时间陷入困境。@Yakk希望该语言/库会发展到std::tuple
没有那么重的地步。是否可以将数组存储在具有tuple
的tuple中?我想你需要std::array
来做这个。你能解释一下吗?@johanneschaub-litb是的,你能。不过仍然有tuple
不能很好地处理的类型。
#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;
}