模板类型

时间:2015-06-10 08:35:14

标签: c++ templates c++11 variadic-templates traits

我有一个特征可以返回有关某个类的一些信息,例如维数:

template< typename T >
struct NumDims;

对于&#34;正常&#34;这课很容易专攻:

template<>
struct NumDims< MyClass >: std::integral_constant< unsigned, 3 >{};

但我有一些沉重的模板类,它们都有一个共同的静态constexpr,如:

template< class T, class U, class V, bool x, bool y, bool z >
struct TemplateClass{
    static constexpr unsigned numDims = ...;
}

一个看起来很丑陋和错误的人:

template< class T, class U, class V, bool x, bool y, bool z >
struct NumDims< TemplateClass<T,U,V,x,y,z> >{
    static constexpr unsigned value = TemplateClass<T,U,V,x,y,z>::numDims;
}

我尝试使用可变参数模板:

template< class... T >
struct NumDims< TemplateClass<T...> >{
    static constexpr unsigned value = TemplateClass<T...>::numDims;
}

但这会使我的编译器崩溃(gcc 4.8.2):
    内部编译器错误:在unify_one_argument中,在cp / pt.c:15506

任何想法都可以做到这一点&#34;探针&#34;方式是什么?

1 个答案:

答案 0 :(得分:4)

您的问题是您的TemplateClass类模板中混合了类型和非类型参数,因此您不能拥有可变参数类型参数。据我所知,目前没有办法混合类型和非类型的参数,没有在非虚拟模板中包装非类型参数。

幸运的是,您可以支持整个问题,并且只有当您传入的类型具有numDims静态成员时才启用部分特化:

template <typename T, typename = void>
struct NumDims;

template<>
struct NumDims< MyClass >: std::integral_constant< unsigned, 3 >{};

template< class T >
struct NumDims< T, void_t<decltype(T::numDims)> >{
    static constexpr unsigned value = T::numDims;
};

这使用了尚未标准的void_t,因此您可以使用这样的简单实现:

template <typename...>
struct voider { using type = void; };
template <typename... Ts> using void_t = typename voider<Ts...>::type;