繁体   English   中英

C++ 常量变量的模板特化

[英]C++ Template specialization for constant variables

我目前正在尝试拥有一个专门用于多种类型的模板的编译时常量变量。 目前,我正在使用常量表达式,例如以下通用示例:

template<typename T>
constexpr T GENERAL_CONSTANT = T(0.01);

template<> constexpr float GENERAL_CONSTANT<float> = float(0.02);

template<> constexpr double GENERAL_CONSTANT<double> = double(0.03);

但是,此代码似乎仅适用于某些编译器/链接器。 It will compile and work correctly for Clang 9.0.0 for Windows 10, Clang 6.0.0 for Windows 10, Clang 6.0.0 for Ubuntu 18.04, and GCC for Ubuntu 18.04. But has given the similar multiple redefinition errors in several other configurations such as Clang 10.0.0 on Windows 10 or Clang 10.0.0 on Unix, as well as a few others. 错误通常看起来类似于:

/usr/bin/ld: <some path to a.cpp> multiple definition of `GENERAL_CONSTANT<double>'; <some path to a.cpp>: first defined here
/usr/bin/ld: <some path to a.cpp> multiple definition of `GENERAL_CONSTANT<float>'; <some path to a.cpp>: first defined here

其中 'a.cpp' 是使用常量但未定义它们的文件。 因此,鉴于此错误根据编译器和机器而不一致地发生,我很好奇这是否是解决此问题的非标准方法,如果这是真的,我应该采取什么方法呢?

变量模板的const限定(并且constexpr确实使 object const )并不意味着内部链接[basic.link]/p3

具有命名空间 scope 的名称如果是

  • 变量,变量模板,function,或 function 模板,显式声明为 static 或者

  • 非 volatile const 限定类型非模板变量,除非 [...]

这似乎是最近的变化( CWG 2387 ):

2018 年 12 月电话会议的注意事项:

CWG 认为const类型不应影响变量模板或其实例的链接。

这解释了您在 Clang-10 中观察到的差异。

作为解决方案,将变量模板及其特化标记为staticinline 前者强制内部链接,而后者从一个定义规则中排除变量模板实例,允许多个定义,前提是它们位于单独的翻译单元中。

此代码按原样编译。 请参阅此演示 即使标记为constexpr ,专用模板变量仍将编译为二进制文件。 由于您使用的是 header 以及多个翻译单元中的这些变量,因此您会收到 linker 错误。 您可以通过ld给您错误的事实来判断这一点。

inline标记专业化将防止这种情况发生并解决问题:

template<typename T>
constexpr T GENERAL_CONSTANT = T(0.01);

template<> inline constexpr float GENERAL_CONSTANT<float> = float(0.02);

template<> inline constexpr double GENERAL_CONSTANT<double> = double(0.03);

这是一个编译器错误,因为constexpr意味着变量和函数的inline ,但显然,某些编译器版本会为模板专业化而搞砸。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM