专用模板类的静态成员初始化

class A
{
};

template <typename A, int S>
class B
{
public:
        static int a[S];

        B()
        {
                a[0] = 0;
        }
};

template<> int B<A, 1>::a[1];

int main()
{
        B<A, 1> t;
        t;
}

它在 GCC 4.1 下编译,但不链接:

It compiles under GCC 4.1, but does not link:

static.cpp:(.text._ZN1BI1ALi1EEC1Ev[B<A, 1>::B()]+0x5): undefined reference to `B<A, 1>::a'

如果可能的话,我更愿意保持专门的初始化,因为数组保存了一些特定于类型的数据.

I would prefer to keep initialisation specialised if it is possible, since the array holds some data specific to the type.

推荐答案

对于静态成员特化,如果不初始化成员,则视为特化声明,只说哦,不要从主模板实例化成员,因为在其他地方有专门的定义".需要说明的是,定义应该出现在.cpp文件中(否则,你会得到相反的结果:多个定义),没有初始化器的声明仍然应该放在头文件中.

For static member specializations, if you don't initialize the member, it is taken as a specialization declaration, that just says "Oh, don't instantiate the member from the primary template, because there is a specialized definition somewhere else". It should be mentioned that the definition should appear in a .cpp file (otherwise, you will earn the opposite: multiple definitions), and the declaration without initializer should still be placed in the header file.

现在正确的语法确实如下,它应该不出现在头文件中,而是出现在.cpp文件中

Now the correct syntax is indeed the following, and it should not appear in a header file, but in a .cpp file

template<> int B<A, 1>::a[1] = { };

以下内容仍应出现在头文件中:

The following should still appear in a header file:

template<> int B<A, 1>::a[1];

这将作为专业化声明.

由此可知,您不能特化一个只有默认构造函数且不可复制的成员,因为您需要以下语法:

From this, it follows that you can't specialize a member that only has a default constructor and is not copyable, because you would need this syntax:

// needs a copy constructor!
template<> Type Class<Arguments>::member = Type();

C++0x 修复了这个:

C++0x fixes this:

// doesn't anymore need a copy constructor
template<> Type Class<Arguments>::member{};

<小时>

对于我们当中的标准人来说,这里是引述:


For the Standardese people among us, here are the quotes:

14.7.3/6:

如果模板、成员模板或类模板的成员是显式特化的,则应在第一次使用该特化之前声明该特化,这将导致隐式实例化发生,在每个翻译单元中,使用发生;不需要诊断.

If a template, a member template or the member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.

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;

这是一个声明,不管 X 是否可以默认初始化(8.5).]

This is a declaration regardless of whether X can be default initialized (8.5). ]

3.2/3:

每个程序都应包含该程序中使用的每个非内联函数或对象的一个??定义;无需诊断.

Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required.

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)[...]

There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.4) in a program [...]

将此限制为未指定某些模板参数"意味着我们可以执行以下操作,将其放入标题中(因此可能具有此专业化的多个定义):

The restriction of this to "for which some template parameters are not specified" means that we are allowed to do the following, placing it into a header (thus possibly having multiple definitions of this specialization):

template<> template<typename T>
Type OuterClass<int>::InnerClass<T>::StaticMember = 0;

在您的情况下,您已经指定了所有参数,因此它不受允许多个定义的单一定义规则的约束.

In your case, you have all parameters specified, making it not being covered by the one defintion rule for allowing multiple definitions.

相关文章