是否有可能“存储”模板参数包,而不扩大它?
当我偶然发现这个问题时,我正在试验C ++ 0x variadic模板:
template < typename ...Args > struct identities { typedef Args type; //compile error: "parameter packs not expanded with '...' }; //The following code just shows an example of potential use, but has no relation //with what I am actually trying to achieve. template < typename T > struct convert_in_tuple { typedef std::tuple< typename T::type... > type; }; typedef convert_in_tuple< identities< int, float > >::type int_float_tuple;
当我尝试键入模板参数包时,GCC 4.5.0给了我一个错误。
基本上,我想“存储”参数包在一个typedef,而不是解压缩它。 可能吗? 如果没有,有没有理由不允许这样做?
另一个比Ben更通用的方法如下:
#include <tuple> template <typename... Args> struct variadic_typedef { // this single type represents a collection of types, // as the template arguments it took to define it }; template <typename... Args> struct convert_in_tuple { // base case, nothing special, // just use the arguments directly // however they need to be used typedef std::tuple<Args...> type; }; template <typename... Args> struct convert_in_tuple<variadic_typedef<Args...>> { // expand the variadic_typedef back into // its arguments, via specialization // (doesn't rely on functionality to be provided // by the variadic_typedef struct itself, generic) typedef typename convert_in_tuple<Args...>::type type; }; typedef variadic_typedef<int, float> myTypes; typedef convert_in_tuple<myTypes>::type int_float_tuple; int main() {}
我认为不允许的原因是它会很混乱,你可以解决它。 您需要使用依赖关系反转,并将存储参数包的结构放入可以将该参数包应用到另一个模板的工厂模板中。
有些东西是:
template < typename ...Args > struct identities { template < template<typename ...> class T > struct apply { typedef T<Args...> type; }; }; template < template<template<typename ...> class> class T > struct convert_in_tuple { typedef typename T<std::tuple>::type type; }; typedef convert_in_tuple< identities< int, float >::apply >::type int_float_tuple;
这是GManNickG整洁的部分专业化技巧的变体。 没有代表团,你需要使用variadic_typedef结构来获得更多的types安全。
#include <tuple> template<typename... Args> struct variadic_typedef {}; template<typename... Args> struct convert_in_tuple { //Leaving this empty will cause the compiler //to complain if you try to access a "type" member. //You may also be able to do something like: //static_assert(std::is_same<>::value, "blah") //if you know something about the types. }; template<typename... Args> struct convert_in_tuple< variadic_typedef<Args...> > { //use Args normally typedef std::tuple<Args...> type; }; typedef variadic_typedef<int, float> myTypes; typedef convert_in_tuple<myTypes>::type int_float_tuple; //compiles //typedef convert_in_tuple<int, float>::type int_float_tuple; //doesn't compile int main() {}
我发现本Voigt的想法在我自己的努力中非常有用。 我已经稍微修改了一下,使它不只是元组。 对这里的读者来说,这可能是一个明显的修改,但可能值得一提:
template <template <class ... Args> class T, class ... Args> struct TypeWithList { typedef T<Args...> type; }; template <template <class ... Args> class T, class ... Args> struct TypeWithList<T, VariadicTypedef<Args...>> { typedef typename TypeWithList<T, Args...>::type type; };
名字TypeWithList源于事实,即types现在被实例化为前一个列表。