请参阅以下内容:
https://zh.cppreference.com/w/cpp/language/definition#One_Definition_Rule
http://eel.is/c++draft/basic.def.odr#12
它声明了类模板的多个定义,类模板的静态数据成员,部分模板专门化等是允许的,并且将作为一个单独的定义。很好...但是在任何地方都没有提到变量模板?
如果我在多个翻译单元中具有以下内容:
template<typename T>
T my_data{};
inline void test() {
my_data<int> = 1;
}
是将为每个翻译单元提供它们自己的定义,以my_data
产生多个符号,还是将它们全部有效地合并到程序中的单个定义中,在其中调用test()
一个翻译单元将为另一个翻译单元修改变量?
它在标准中哪里提到了此行为?
根据c ++ 14标准[basic.def] / 4:
每个程序应准确地包含在该程序中被丢弃的语句之外的每个非内联函数或变量的一个定义;无需诊断。
因此,如果my_data<T>
在多个翻译单元中与相同的模板参数一起使用ord,则应该具有odr-violation(无任何诊断)。inline
变量出现在c ++ 17中以解决该问题,这就是为什么声明type_traits
* _v系列变量模板的原因inline
。
在实践中,使用Gcc和Clang(至少,我无法检查其他编译器),因为模板变量具有“模糊链接”(就像它们被声明为内联一样),您将不会遇到任何odr违例。
您可以使用进行检查nm
。如果运行此命令行g++ -c test.cpp -std=c++14 && nm test.o | c++filt | grep my_data
,应该看到这是根据文档my_data<int>
的categorie的符号:u
nm
该符号是唯一的全局符号。这是对ELF符号绑定的标准集合的GNU扩展。对于这样的符号,动态链接器将确保在整个过程中只有一个使用此名称和类型的符号。
在核心问题#1849中,您可以阅读以下晦涩的句子:
在6.2 [basic.def.odr]第6段中,何时可以在程序中多次声明实体的描述不是,但应该讨论变量模板。
我敢打赌,如果所有编译器都为变量模板提供模糊的链接,那么将来对该标准的修订可能会反映出这一点。但是现在我们应该像在stl中那样使用内联说明符。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句