template<typename T>
struct A{
void method1(){}
};
template<>
struct A<int>{
void method2(){}
};
A<int>
是否同时包含method1和method2? A<float>
只有method1
?
答案 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>
有成员method1
和method2
,但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()
。