我们有一个头文件,其中包含各种浮点精度的一些残差:
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
初始化可能需要进入源文件并从头文件中取出。但是,似乎禁止在extern
前面const double
。
我需要做些什么才能使用多个编译单元?
我认为为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需要,对吗?)。哪种解决方案也适用于此?
答案 0 :(得分:1)
您可以允许所有这些定义驻留在头文件中,而不会在多个翻译单元中使用时导致链接器错误,您只需要将它们转换为模板:
template<typename T, typename TDummy = void>
struct rsdTarget;
template<typename TDummy>
struct rsdTarget<half, TDummy>
{
static const double value;
};
template<typename TDummy>
const double rsdTarget<half, TDummy>::value = (double)(1.0e-3);
template<typename TDummy>
struct rsdTarget<float, TDummy>
{
static const double value;
};
template<typename TDummy>
const double rsdTarget<float, TDummy>::value = (double)(1.0e-7);
template<typename TDummy>
struct rsdTarget<double, TDummy>
{
static const double value;
};
template<typename TDummy>
const double rsdTarget<double, TDummy>::value = (double)(1.0e-12);
答案 1 :(得分:1)
之前的C ++ 1z
template<typename>
struct rsdTarget;
template<>
struct rsdTarget<half>
{
static constexpr double value = 1e-3;
};
// and so on...
这有一个限制value
不能使用,但在大多数情况下,这不是常数的问题。
发布C ++ 1z后,你可以使用inline
个变量,避免整个骚乱。