本文介绍了专用模板类的静态成员初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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:

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

14.7.3/15:

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

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:

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

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

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

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.

这篇关于专用模板类的静态成员初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-27 15:54
查看更多