C++ C++;常量变量的模板专门化

C++ C++;常量变量的模板专门化,c++,templates,compile-time-constant,C++,Templates,Compile Time Constant,我目前正在尝试使用一个编译时常量变量,该变量是专门用于几种类型的模板。目前,我正在使用常量表达式,如以下通用示例: 模板 constexpr T一般常数=T(0.01); 模板constexpr float GENERAL_常量=float(0.02); 模板constexpr-double-GENERAL_常数=double(0.03); 然而,这段代码似乎只适用于某些编译器/链接器。它将编译并正确运行于适用于Windows 10的Clang9.0.0、适用于Windows 10的Clang

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

模板
constexpr T一般常数=T(0.01);
模板constexpr float GENERAL_常量=float(0.02);
模板constexpr-double-GENERAL_常数=double(0.03);
然而,这段代码似乎只适用于某些编译器/链接器。它将编译并正确运行于适用于Windows 10的Clang9.0.0、适用于Windows 10的Clang6.0.0、适用于Ubuntu 18.04的Clang6.0.0和适用于Ubuntu 18.04的GCC。但在其他一些配置中也出现了类似的多个重新定义错误,如Windows 10上的Clang 10.0.0或Unix上的Clang 10.0.0,以及其他一些配置。这些错误通常与此类似:

/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
/usr/bin/ld:GENERAL_常量的多重定义;:首先在这里定义
/usr/bin/ld:“一般_常数”的多重定义;:首先在这里定义

其中“a.cpp”是使用常数但未定义常数的文件。因此,鉴于此错误的发生取决于编译器和机器,我很好奇这是否是解决此问题的非标准方法,如果这是真的,我应该采取什么方法来代替?

此代码确实按原样编译。看见 即使标记为
constexpr
,专用模板变量仍将编译成二进制。由于您在多个翻译单元中使用了标题和这些变量,因此会出现链接器错误。 您可以通过
ld
给出错误的事实来判断这一点

将专门化标记为内联将防止这种情况发生并解决问题:

模板
constexpr T一般常数=T(0.01);
模板内联constexpr float GENERAL_常量=float(0.02);
模板内联常量表达式双通用常量=双(0.03);

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

const
变量模板的限定(并且
constepr
会生成对象
const
)并不意味着内部链接:

具有命名空间作用域的名称如果是的名称,则具有内部链接

  • 变量、变量模板、函数或显式声明为静态的函数模板;或

  • 非易失性常量限定类型的非模板变量,除非[…]

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

2018年12月电话会议记录:

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

这就解释了你在Clang-10中观察到的差异


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

您可以将其包装为结构。此外,它应该是
template constexpr float GENERAL\u CONSTANT=float(0.02)
@PiotrSkotnicki您是对的,我忘记添加上面的模板参数,但在我的代码中有它。至于更多细节,变量模板是在头文件中定义的,常量只在实现类/结构的源文件中使用,这些类/结构也是按类型模板化的,即float和double。啊,好的,很高兴知道,添加inline关键字似乎解决了有问题配置的问题。谢谢你的帮助!这不是编译器错误。对于非成员变量,
constepr
都不意味着
inline
。您的意思可能是“内部链接”。好的,很高兴知道,添加“inline”关键字似乎对有问题的配置有效。我认为从你给出的概要来看,使用“内联”将是我使用的最佳选择。谢谢