模板专门化是否扩展或覆盖通用模板?

时间:2013-05-27 01:09:20

标签: c++ templates

template<typename T>
struct A{
    void method1(){}
 };

template<>
struct A<int>{
    void method2(){}
 };

A<int>是否同时包含method1和method2? A<float>只有method1

3 个答案:

答案 0 :(得分:16)

每个专业化都会带来一种全新的数据类型(如果专业化只是部分的话,则会产生一个全新的模板)。从标准(C ++ 11):

  

(§14.5.5/ 2)每个类模板部分特化是一个不同的模板,应为模板部分特化的成员提供定义(14.5.5.3)。

  

(§14.5.5.3/ 1)[...]类模板部分特化的成员与主模板的成员无关。应定义以需要定义的方式使用的类模板部分特化成员;主模板成员的定义从不用作类模板部分特化的成员的定义。 [...]

以上是在部分特化的上下文中说明的,但它也适用于显式特化(如在您的情况下),尽管标准没有这么清楚地说明。

另请注意,您不仅需要在专业化中声明所需的所有成员函数,还需要定义它们(此处,标准对于显式特化非常清楚):

  

(14.7.3 / 5)显式专用类的成员不是从类模板的成员声明中隐式实例化的;相反,如果需要定义,则类模板特化的成员本身应明确定义。在这种情况下,类模板显式特化的定义应在范围内   在定义成员的位置。明确专用类的定义与生成的专门化的定义无关。也就是说,其成员不必具有与生成的专业化的成员相同的名称,类型等。 [...]

所以,的确,A<int>只有method2()A<float>只有method1()成员。此外,如果您要在method1()专门化中引入A<int>,则它不需要具有与A<float>::method1()相同的参数类型或返回类型。

请参阅@ aschepler的答案,了解避免必须重写int案例的模板定义的可能方法。

答案 1 :(得分:12)

@ jogojapan的回答解释了语言的作用。如果您确实想为特定专业化添加新成员,可以使用以下几种解决方法:

template<typename T>
struct A_Base {
    void method1() {}
};

template<typename T>
struct A : public A_Base<T> {};

template<>
struct A<int>
  : public A_Base<int>
{
    void method2() {}
};

现在A<int>有成员method1method2,但A<float>没有method2

OR(如果您可以修改主模板)......

#include <type_traits>

template<typename T>
struct A {
    void method1() {}

    template<int N=0>
    auto method2() ->
    typename std::enable_if<std::is_same<T, int>::value && N==N>::type
    {}
};

template<int N>N==N部分确保std::enable_if具有相关值,因此在有人实际尝试使用A<T>::method2 T之前不会抱怨参数。

答案 2 :(得分:2)

专业化取代了通用模板。因此A<int>只有method2(),当然,A<double>只会有method1()