75

当我偶然发现这个问题时,我正在尝试使用 C++0x 可变参数模板:

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;

当我尝试 typedef 模板参数包时,GCC 4.5.0 给我一个错误。

基本上,我想将参数包“存储”在 typedef 中,而不是将其解包。是否可以?如果不是,是否有某些原因不允许这样做?

4

4 回答 4

57

另一种比 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()
{}
于 2011-01-14T16:42:39.347 回答
10

我认为不允许这样做的原因是它会很乱,你可以解决它。您需要使用依赖倒置并使将参数包存储到工厂模板中的结构能够将该参数包应用于另一个模板。

类似于以下内容:

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;
于 2011-01-14T14:31:46.747 回答
3

我发现 Ben 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 源于该类型现在使用以前的列表进行实例化。

于 2013-09-04T10:56:41.533 回答
2

这是 GManNickG 巧妙的偏特化技巧的一种变体。没有委托,并且通过要求使用 variadic_typedef 结构,您可以获得更多的类型安全性。

#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() {}
于 2013-02-18T01:08:38.427 回答