template<typename T>
struct A{
void method1(){}
};
template<>
struct A<int>{
void method2(){}
};
会有A<int>
method1和method2吗?而且A<float>
只会有method1
?
每个特化都带来了一个全新的数据类型(或者一个全新的模板,如果特化只是部分的)。从标准(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 的答案。
@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
。
或者(如果您可以修改主模板)...
#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
而且由于这个问题和答案似乎仍然受到关注,稍后编辑以在 C++20 中添加它,您可以简单地执行以下操作:
#include <type_traits>
template<typename T>
struct A {
void method1() {}
void method2() requires std::is_same_v<T, int> {}
};
专业化取代了通用模板。所以A<int>
只会有method2()
,当然A<double>
也只会有method1()
。