全局变量和 constexpr(是否内联?)

Global variables and constexpr (inline or not?)

如果我有:a.hpp a.cpp 和 main.cpp 包括 a.hpp,并且在 a.hpp 我写

template<typename T>
constexpr int num;
template<>
constexpr int num<float> = 1;
template<>
constexpr int num<double> = 2;

我是否冒着在 a.o 和 main.o 中多次定义变量 num 的风险?还是声明为内联?我应该将模板变量特化放在 a.cpp 中吗?如果我将 a.hpp 包装到命名空间中会发生什么变化?

Do I risk defining the variable num multiple times both in a.o and main.o?

是的。对于非模板变量,constexpr 意味着 const 并且 const 在名称空间级别意味着内部 linkage,但不适用于变量模板。似乎这在标准中没有明确规定。目前的草案有以下内容

Note 1: An instantiated variable template that has const-qualified type can have external or module linkage, even if not declared extern.

根据实验,不同的编译器赋予它们不同的 linkage。例如,GCC 9.3.0 和 10.2.0 num<float> 有内部 linkage:

nm -C a.o
...
0000000000000004 r num<float>

但对于 Clang 10.0.0,它具有外部 linkage:

nm -C a.o
...
0000000000000000 R num<float>

因此,如果您尝试在两个编译单元中包含 a.hpp,Clang 会出现 link 错误。


Or is it declared inline?

否,需要显式 inline

What changes if I wrap a.hpp into a namespace?

我猜你说的是未命名的命名空间。在这种情况下,保证每个编译单元都有自己的(私有)副本。