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

joh*_*ers 9 c++ templates

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

template<>
struct A<int>{
    void method2(){}
 };
Run Code Online (Sandbox Code Playgroud)

方法1 A<int>和方法2都有?而且A<float>只会有method1

jog*_*pan 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案例的模板定义的可能方法.


asc*_*ler 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() {}
};
Run Code Online (Sandbox Code Playgroud)

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

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

#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
    {}
};
Run Code Online (Sandbox Code Playgroud)

template<int N>N==N部分确保std::enable_if有一个相关的值,因此不会抱怨,直到有人实际上是尝试用A<T>::method2用不正确的T参数.