【发布时间】:2017-07-20 09:24:27
【问题描述】:
我们有一个头文件,其中包含各种浮点精度的一些残差:
template <typename T>
struct rsdTarget {
static const double value;
};
template <>
const double rsdTarget<half>::value = (double)(1.0e-3);
template <>
const double rsdTarget<float>::value = (double)(1.0e-7);
template <>
const double rsdTarget<double>::value = (double)(1.0e-12);
这很有效,因为这个头文件只包含在一个编译单元中。现在我尝试在多个编译单元中使用这个头文件,我得到了源于 ODR 的链接器错误:
CMakeFiles/tests_g.dir/random_gauge.cc.o:(.rodata+0x108): multiple definition of `rsdTarget<double>::value'
CMakeFiles/tests_g.dir/clover_product.cc.o:(.rodata+0x548): first defined here
初始化可能需要进入源文件并从头文件中取出。但是,似乎禁止在const double 前面加上extern。
我必须怎么做才能使其适用于多个编译单元?
更新
我认为为double 解决这个问题会完全解决它。但是,我还必须执行第二种非文字类型:
template <typename T>
struct tolerance {
static const QDP::Double small; // Always fail
};
template <>
const QDP::Double tolerance<half>::small = QDP::Double(5.0e-3);
template <>
const QDP::Double tolerance<float>::small = QDP::Double(1.0e-6);
template <>
const QDP::Double tolerance<double>::small = QDP::Double(1.0e-7);
我似乎无法将它与constexpr 一起使用,因为该类型不支持它(需要constexpr ctor,对吗?)。哪些解决方案也适用于此?
【问题讨论】:
-
在专业化上使用
inline。 (如果您使用的是最新的编译器,请考虑将其替换为内联变量) -
您也可以在 Microsoft 编译器的模板专业化之前使用
__declspec(selectany)。 -
内联变量似乎需要C++17,我们现在只到C++11。它是一种高性能代码,需要在编译器版本不可预测的各种 HPC 系统上运行。我会试着摆弄内联。
-
@ikleschenkov:我没有看到我们使用过微软编译器。我们使用 GCC、Clang、IBM XLC(虽然不适用于此代码)、英特尔 C++ 和 Cray 编译器。我们的目标系统在 Linux 上运行 :-)。
-
我已经更新了问题,因为问题比我想象的要严重。很抱歉!
标签: c++ c++11 one-definition-rule