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

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

会有A<int>method1和method2吗?而且A<float>只会有method1

4

3 回答 3

21

每个特化都带来了一个全新的数据类型(或者一个全新的模板,如果特化只是部分的)。从标准(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().

int有关避免为案例重写模板定义的可能方法,请参阅@aschepler 的答案。

于 2013-05-27T01:35:43.897 回答
18

@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

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

#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==Nstd::enable_ifA<T>::method2T


而且由于这个问题和答案似乎仍然受到关注,稍后编辑以在 C++20 中添加它,您可以简单地执行以下操作:

#include <type_traits>

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

    void method2() requires std::is_same_v<T, int> {}
};
于 2013-05-27T02:34:34.497 回答
2

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

于 2013-05-27T01:13:00.610 回答