2013-05-27 75 views

回答

13

每个专业化都会带来一种全新的数据类型(或者如果专业化只是部分的话,则是一个全新的模板)。从标准(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()作为成员。此外,如果您要在A<int>专业化中引入method1(),则它不需要具有与A<float>::method1()相同的参数类型或返回类型。

请参阅@ aschepler的答案,以避免必须重写int案例的模板定义。

+1

@Fellowshee是的,你可以做到这一点。在这种情况下,不申报新的'模板<>结构一个 {...};',而只是声明(和定义)要专门的方法:'一个 ::方法1(){.. 。};类外部模板定义。 – jogojapan

+0

有趣的是,课堂内部没有提及的课堂外声明和定义被认为是合法的? – johnbakers

+0

@Fellowshee哦,对不起,我以为你需要在'int'情况下使用'method1'的专门化。如果你真的需要为'int'情况添加一个全新的'method2',那么的确需要重写整个模板int。根据情况,最好将'method2'添加到主模板定义中,但将其保留为未定义(或让它抛出异常,或放入'static_asssert(false,“not implemented”);后者只适用于C++ 11))。这样你可以专注于'int'情况下的'method2'而不必重写整个模板。 – jogojapan

1

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

+0

我想那么编译器将把它们作为完全独立的班级,他们之间没有任何关系,因为如果他们有完全不同的名字(这在创建的源,他们可能做什么?) – johnbakers

+0

从模板生成的每个类型是完全与同一模板生成的其他类型完全没有关系。这没有什么区别。 '一个','一个'和'一个'是三个不相关的类。 – Gorpik

9

@ 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参数。

+0

+1,尤指为enable-if技术。 – jogojapan

+0

@aschepler - 如果'A_Base' *不是*模板,第一种技术(非C++ 11技术)会工作吗?也就是说,你可以有一个'A :: A_Base :: method2'吗?我从MSVC中收到一个错误,我从来没有看到错误([C2936](https://msdn.microsoft.com/en-us/library/ctfzt48x.aspx))。我不确定它不可能,不可能用C++ 03,或者它是MSVC的限制。 – jww

+0

@jww是的,它应该工作。我不确定为什么你会得到这个错误。您链接的页面建议检查不匹配的大括号。如果你还没有看到一个愚蠢的错误,你可能想编写和测试一个[mcve]并发布一个关于它的新问题。 – aschepler