在 .h 文件中定义的模板类静态成员变量会发生什么
如果模板类定义包含依赖于模板类型的静态成员变量,我不确定可靠的行为应该是什么?
If a template class definition contains a static member variable that depends on the template type, I'm unsure of what the reliable behavior should be?
就我而言,最好将该静态成员的定义与类定义放在同一个 .h 文件中,因为
In my case it is desirable to place the definition of that static member in the same .h file as the class definition, since
- 我希望该类适用于我目前没有的许多模板数据类型知道.
- 我只想共享静态成员的一个实例在我的每个给定模板类型的程序中.(一个用于所有
MyClass
,一个用于所有MyClass
,等等.
- I want the class to be general for many template data types that I don't currently know.
- I want only one instance of the static member to be shared
throughout my program for each given template type. ( one for all
MyClass<int>
and one for allMyClass<double>
, etc.
我可以最简短地说,在此链接列出的代码在编译时完全符合我的要求使用 gcc 4.3.这种行为是否符合 C++ 标准,以便我在使用其他编译器时可以依赖它?
I can be most brief by saying that the code listed at this link behaves exactly as I want when compiled with gcc 4.3. Is this behavior according to the C++ Standard so that I can rely on it when using other compilers?
那个链接不是我的代码,而是一个由 CodeMedic 发布到讨论中的反例 此处.我发现了其他几个像这样的辩论一个,但我没有考虑结论性的.
That link is not my code, but a counter example posted by CodeMedic to the discussion here. I've found several other debates like this one but nothing I consider conclusive.
我认为链接器正在整合找到的多个定义(在示例 a.o
和 b.o
中).这是必需的/可靠的链接器行为吗?
I think the linker is consolidating the multiple definitions found ( in the example a.o
and b.o
).
Is this the required/reliable linker behavior?
推荐答案
来自 N3290, 14.6:
From N3290, 14.6:
类模板的 [...] 静态数据成员应在每个翻译单元在其中隐式实例化 [...] ,除非相应的专业化显式实例化 [...] .
A [...] static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated [...], unless the corresponding specialization is explicitly instantiated [...] .
通常,您将静态成员定义与模板类定义一起放在头文件中:
Typically, you put the static member definition in the header file, along with the template class definition:
template <typename T>
class Foo
{
static int n; // declaration
};
template <typename T> int Foo<T>::n; // definition
扩展让步:如果您计划在代码中使用显式实例,例如:
To expand on the concession: If you plan on using explicit instantiations in your code, like:
template <> int Foo<int>::n = 12;
那么如果 Foo
也用于其他 TU 中而不是包含显式实例化的 TU,则您必须不要将模板化定义放在标题中,因为您'd 然后得到多个定义.
then you must not put the templated definition in the header if Foo<int>
is also used in other TUs other than the one containing the explicit instantiation, since you'd then get multiple definitions.
但是,如果您确实需要在不使用显式实例化的情况下为所有可能的参数设置初始值,则必须将其放在标题中,例如使用 TMP:
However, if you do need to set an initial value for all possible parameters without using explicit instantiation, you have to put that in the header, e.g. with TMP:
// in the header
template <typename T> int Foo<T>::n = GetInitialValue<T>::value; // definition + initialization
相关文章