在.h文件中定义的模板类静态成员变量应该发生什么?

What should happen to template class static member variables with definition in the .h file

本文关键字:变量 什么 静态成员 文件 定义      更新时间:2023-10-16

如果模板类定义包含依赖于模板类型的静态成员变量,我不确定可靠的行为应该是什么?

在我的例子中,最好将该静态成员的定义与类定义放在同一个.h文件中,因为

  1. 我希望类是通用的许多模板数据类型,我目前没有知道。
  2. 我只想要共享静态成员的一个实例在我的程序中为每个给定的模板类型。(一个用于所有MyClass<int>,一个用于所有MyClass<double>,等等)

我可以最简短地说,这个链接中列出的代码在使用gcc 4.3编译时的行为完全符合我的要求。这种行为是否符合c++标准,以便我在使用其他编译器时可以依赖它?

那个链接不是我的代码,而是CodeMedic在这里讨论的一个反例。我发现了其他一些类似的辩论,但我认为没有一个是决定性的。

我认为链接器正在巩固发现的多个定义(在示例a.ob.o中)。这是必需的/可靠的链接器行为吗?

From N3290, 14.6:

[…类模板的静态数据成员定义在每个被隐式实例化的翻译单元[…]],除非相应的专门化被显式实例化[…]] .

通常,将静态成员定义与模板类定义一起放在头文件中:
template <typename T>
class Foo
{
  static int n;                       // declaration
};
template <typename T> int Foo<T>::n;  // definition

如果你打算在你的代码中使用显式实例化,比如:

template <> int Foo<int>::n = 12;

那么,如果Foo<int>也在包含显式实例化的tu之外的其他tu中使用,则必须将模板化的定义放在头文件中,因为这样会得到多个定义。

但是,如果您确实需要为所有可能的参数设置初始值而不使用显式实例化,则必须将其放在头文件中,例如TMP:

// in the header
template <typename T> int Foo<T>::n = GetInitialValue<T>::value;  // definition + initialization

这完全是对@Kerrek SB出色答案的补充。我想把它作为评论添加,但是已经有很多评论了,所以默认情况下新的评论是隐藏的。

所以,他的例子和我看到的其他例子都是"简单的",因为静态成员变量的类型是事先已知的。这很容易,因为例如编译器知道任何模板实例化的存储大小,所以有人可能会认为编译器可以使用时髦的mangling方案,输出一次变量定义,并将其余部分卸载给链接器,这甚至可能工作。

但是令人惊讶的是,当静态成员类型依赖于模板形参时,它可以工作。例如:

template <typename width = uint32_t>
class Ticks : public ITimer< width, Ticks<width> >
{
protected:
    volatile static width ticks;
}
template <typename width> volatile width Ticks<width>::ticks;

(注意,静态变量的显式实例化不需要(或允许)默认的width规格)。

因此,它带来了更多的想法,c++编译器必须做相当多的处理-特别是,为了实例化模板,不仅需要模板本身,而且还必须收集所有的[static member]显式实例化(人们可能只会奇怪为什么它们是单独的语法结构,而不是在模板类中详细说明)。

对于链接器级别的实现,对于GNU binutils它的"通用符号":http://sourceware.org/binutils/docs/as/Comm.html通讯。(对于微软工具链,它被命名为COMDAT,正如另一个答案所说)。

链接器对这种情况的处理几乎与应用了__declspec(selectany)声明的非模板类静态成员完全相同,如下所示:

class X {
public:
X(int i){};
};
__declspec(selectany) X x(1);//works in msvc, for gcc use __attribute__((weak))

正如msdn所说:"在链接时,如果看到COMDAT的多个定义,链接器会选择一个并丢弃其余的…对于动态初始化的全局对象,selectany也会丢弃未引用对象的初始化代码。"

相关文章: