如果我有:a.hpp a.pp和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的风险?或者它是内联声明的?我应该把模板变量专业化放在.cpp里吗?如果将.hpp封装到命名空间中,会发生什么变化?
我是否有在a.o和main.o中多次定义变量
num
的风险?
确实如此。对于非模板变量,constexpr
表示const
,而命名空间级别的const
表示内部链接,但不适用于变量模板。这一点在标准中似乎没有明确规定。目前的草案有以下
注意1:具有
const
限定类型的实例化变量模板可以具有外部或模块链接,即使没有声明为extern
。
在实验中,不同的编译器为它们提供了不同的链接。例如,对于GCC 9.3.0和10.2.0,num<float>
具有内部链接:
nm -C a.o ... 0000000000000004 r num<float>
,但Clang 10.0.0具有外部链接:
nm -C a.o ... 0000000000000000 R num<float>
因此,如果您试图将a.hpp
包含在两个编译单元中,则Clang会出现链接错误。
或者它是内联声明的?
否,需要显式inline
。
如果将.hpp封装到命名空间中,会发生什么变化?
我猜你说的是一个未命名的命名空间。在这种情况下,每个编译单元都保证获得自己的(私有(副本。