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

kas*_*spy 17 c++ static templates initialization specialization

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果可能的话,我宁愿保持初始化专用,因为数组包含特定于该类型的一些数据.

Joh*_*itb 35

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

现在正确的语法的确以下,应该不会出现在头文件,但在一个.cpp文件

template<> int B<A, 1>::a[1] = { };
Run Code Online (Sandbox Code Playgroud)

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

template<> int B<A, 1>::a[1];
Run Code Online (Sandbox Code Playgroud)

这将作为专业化宣言.


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

// needs a copy constructor!
template<> Type Class<Arguments>::member = Type();
Run Code Online (Sandbox Code Playgroud)

C++ 0x解决了这个问题:

// doesn't anymore need a copy constructor
template<> Type Class<Arguments>::member{};
Run Code Online (Sandbox Code Playgroud)

对于我们中间的Standardese人,以下是引用:

14.7.3/6:

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

14.7.3/15:

如果声明包含初始化器,则模板的静态数据成员的显式特化是定义; 否则,这是一个声明.[注意:对于需要默认初始化的模板的静态数据成员的定义,没有语法.

template<> X Q<int>::x;
Run Code Online (Sandbox Code Playgroud)

无论X是否可以默认初始化(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;
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您指定了所有参数,使其不被允许多个定义的一个定义规则所覆盖.


ken*_*ytm 2

您需要实际为其分配一个值。

template<> int B<A, 1>::a[1] = {0};
Run Code Online (Sandbox Code Playgroud)