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

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required.

因此,如果my_data< T>如果在多个翻译单元中使用相同的模板参数,则应该有一个odr违规(没有任何诊断).内联变量出现在c 17中以解决该问题,这就是为什么type_traits * _v系列变量模板被内联声明的原因.

在实践中,使用Gcc和Clang(至少,我不能检查其他编译器),你不会得到任何odr违规,因为模板变量具有“模糊的链接”(就好像它们被声明为内联).

你可以用nm检查它.如果你运行这个命令行g -c test.cpp -std = c 14&& nm test.o | c filt | grep my_data,你应该看到my_data< int>是根据nm文档的类别的符号:

The symbol is a unique global symbol. This is a GNU extension to the standard set of ELF symbol bindings. For such a symbol the dynamic linker will make sure that in the entire process there is just one symbol with this name and type in use.

Core issue #1849年,人们可以阅读这个不起眼的句子:

The description in 6.2 [basic.def.odr] paragraph 6 of when entities can be multiply-declared in a program does not, but should, discuss variable templates.

我敢打赌,如果所有编译器都给变量模板一个模糊的联系,那么标准的未来修订可能会反映出来.但是现在我们应该使用内联说明符,因为它在stl中完成.

点赞