c++ - 模板变量是否允许在多个翻译单元中并有效合并?
问题描述
请参阅以下内容:
https://en.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>
在多个翻译单元中与相同的模板参数一起使用,您应该有一个 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>
的类别符号:u
nm
该符号是唯一的全局符号。这是标准 ELF 符号绑定集的 GNU 扩展。对于这样的符号,动态链接器将确保在整个过程中只有一个具有此名称和类型的符号在使用中。
在核心问题 #1849中,人们可以读到这个晦涩的句子:
6.2 [basic.def.odr] 第 6 段中关于何时可以在程序中多次声明实体的描述没有但应该讨论变量模板。
我敢打赌,如果所有编译器都给变量模板一个模糊的链接,那么未来的标准修订版可能会反映这一点。但现在我们应该使用 inline 说明符,因为它在 stl 中完成。
推荐阅读
- javascript - 如何在 python selenium webdriver 中使用 javascript 代码通过 xpath 查找 web 元素?
- python - 如何从带有硒的“a”标签中获取href文本
- monetdb - 是否可以将 monetdb/e 构建为静态库?
- r - 我如何在 R 中矢量化(自动化)绘图创建
- node.js - 如何在connection.query函数nodejs中设置一个值
- php - 将键更改为二维数组
- php - 如何使用路由命名空间?
- html - 在 flexbox 中使图像和文本大小相同
- java - Java Socket 编程:连接被拒绝异常
- java - Java 字符串操作 x 带有 y 元素的行数