我有一个可变参数模板类型列表:
template <class... Types>
struct typelist {};
然后我如何将它传递给一些需要参数包的外部代码,比如std::tuple
。换句话说,我需要将参数包存储为我的类型列表中的成员或typedef,如
...
struct typelist {
using types = Types; // Imaginary syntax
}
然而,编译器拒绝了这种情况,称类型未展开。
任何解决方法?
此问题在comments of this question中以另一种方式提及,但现有答案未涵盖。
评论中要求的详细信息:
如果我编译(-std = c ++ 17):
template <class... T>
struct typelist {};
std::tuple<typelist<int, int>> tp{0,1};
g ++给出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};
如果我编译(-std = c ++ 17):
template <class... T>
struct typelist {
using types = T;
};
g++
提供error: parameter packs not expanded with ‘...’:
using types = T;
答案 0 :(得分:4)
您需要一些样板来从tuple
中获得正确的typelist
专业化,因为您无法按原样存储参数包。
例如,您可以通过正确使用函数声明和使用声明来实现:
#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, "!");
}
或者类似于以下示例中的辅助类:
#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, "!");
}
否则,让typelist
公开tuple
专精并直接从中获取:
#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, "!");
}
如果它是您想要使用参数包的唯一类型,这是最简单的方法。
答案 1 :(得分:2)
您无法在参数包中存储类型别名。您需要使用模板参数推导来提取type_list
的参数以供重用。一种方法是使用像这样的虚拟函数:
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>>);
}