![](/img/trans.png)
[英]Template instantiation in different translation units compiled with different optimization levels
[英]explicit instantiation of static variable of a template class in different translation units
我正在使用包含静态变量的模板类。 代码结构如下。
template<class T> class Foo
{
public:
static int count;
Foo() {
count++;
}
void printCount() {
cout << count << endl;
}
};
template<class T> int Foo<T>::count;
#include "Header.h"
template<> int Foo<int>::count = 5;
#include <iostream>
using namespace std;
#include "Header.h"
int main()
{
Foo<int> obj1;
Foo<int> obj2;
obj1.printCount();
obj2.printCount();
return 0;
}
xcode8.3.3上的输出是:
7
7
而Visual Studio 2015的输出为:
2
2
也就是说,特定的实例化将覆盖xcode8.3.3中的通用实例化,但在Visual Studio 2015中则不起作用。有人可以解释这种行为差异吗? 提前致谢。
虽然您的代码包含违反约束的条件,但实际上使其结构良好并维护初始化静态变量的位置并不难。 对于C ++标准,请在[temp.expl.spec] / 13中说 :
如果声明包含初始化程序,则模板的静态数据成员的显式专业化或静态数据成员模板的显式专业化是定义。 否则,它是一个声明。 [注意:需要默认初始化的模板的静态数据成员的定义必须使用大括号初始化列表:
template<> X Q<int>::x; // declaration template<> X Q<int>::x (); // error: declares a function template<> X Q<int>::x { }; // definition
—尾注]
以上暗示仅添加此行
template<> int Foo<int>::count; // declaration
在Header.h的底部足以让所有翻译单元知道Foo<int>::count
存在“某处”。 一个正确的定义可以保留在Source.cpp中 。
您的程序无效:
[ temp.expl.spec#6 ] 如果模板,成员模板或类模板的成员是显式专门化的,则应在首次使用该专门化之前声明该专门化,这将导致隐式实例化。发生这种使用的每个翻译单位; 无需诊断。
换句话说,翻译部门应该就模板名称的含义达成一致。
下一个标准段落简化了:
[...基本上,任何模板...]的显式专门化声明的位置, 都可以根据显式专门化声明的相对位置及其在翻译单元中的实例化点,来影响程序是否格式正确。在上面和下面指定。 编写专长时,请注意其位置; 或将其编译将是点燃其自焚的审判 。
gcc抱怨双重实例:
/tmp/ccUEOg7s.o:(.bss._ZN3FooIiE5countE[_ZN3FooIiE5countE]+0x0): multiple definition of `Foo<int>::count'
/tmp/ccG7CO9C.o:(.data+0x0): first defined here
因此,拥有两个实例和一个链接器无法看到此内容,则任何结果都可能是效果。
在这里拥有变量的两个实例是一个简单的失败,无论是否是模板实例,它们都是独立的。 您必须删除其中之一。
如果使用C ++ 17,则可以在标头中使用var inline。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.