对于静态成员的特化,如果您不初始化该成员,则会将其视为一个专门的
声明,仅表示“哦,不要从主模板实例化该成员,因为在其他地方有一个专门的定义”。应当指出,定义应该出现在.cpp文件中(否则,您将得到相反的结果:多个定义),而没有初始化器的声明仍应放置在头文件中。
现在正确的语法确实是以下内容,它不应该出现在头文件中,而是应该出现在
.cpp
文件中。
template<> int B<A, 1>::a[1] = { };
以下内容仍应出现在头文件中:
template<> int B<A, 1>::a[1];
这将作为专业声明。
由此可见,您无法专门化仅具有默认构造函数且不可复制的成员,因为您需要使用此语法:
// needs a copy constructor!
template<> Type Class<Arguments>::member = Type()
C++0x修复了这个问题:
// doesn't anymore need a copy constructor
template<> Type Class<Arguments>::member{};
对于我们中的标准化专家,以下是引用:
14.7.3/6
:
如果模板、成员模板或类模板的成员被明确地特化,则该特化应在第一次使用该特化之前声明,该使用将导致隐式实例化,在每个出现这样的使用的翻译单位中。 不需要诊断。
14.7.3/15
:
An explicit specialization of a static data member of a template is a definition if the declaration includes an initializer; otherwise, it is a declaration. [Note: there is no syntax for the definition of a static data member of a template that requires default initialization.
template<> X Q<int>::x;
This is a declaration regardless of whether X can be default initialized (8.5). ]
3.2/3
:
每个程序应该包含在程序中使用的每个非内联函数或对象的确切定义;不需要进行任何诊断。
3.2/5
:
一个程序中可以有多个类类型(第9条),枚举类型(7.2),具有外部链接的内联函数(7.1.2),类模板(第14条),非静态函数模板(14.5.5),类模板的静态数据成员(14.5.1.3),类模板的成员函数(14.5.1.1)或一些模板参数未指定的模板特化(14.7,14.5.4)的定义[...]
这个限制是针对“一些模板参数未指定”的,这意味着我们允许执行以下操作,将其放入标头中(因此可能有多个此专业化的定义):
template<> template<typename T>
Type OuterClass<int>::InnerClass<T>::StaticMember = 0
在您的情况下,您已经指定了所有参数,因此不受允许多个定义的一个定义规则的覆盖。
typename A
做任何事情。 - Mike DeSimone