我不得不从g ++ - 4.6切换到4.7(所以我可以使用一些C ++ 11功能)。现在,编译器抱怨:
In function WordJIT<float>::WordJIT(): undefined reference to JitRegType<float>::Val_t
我想知道这些编译器版本之间是否存在可能影响符号解析的内容。或者在新版本(4.7)中更好地实现了语言,我正在做的是错误的:(相同的代码用4.6编译)
class Jit {
public:
enum RegType { f32=0,f64=1,u16=2,u32=3,u64=4,s16=5,s32=6,s64=7 };
// ...
};
template <class T> struct JitRegType {};
template <> struct JitRegType<float> { static const Jit::RegType Val_t = Jit::f32; };
#include "jit.h"
template<class T>
class WordJIT
{
WordJIT() {
mapReg.insert( std::make_pair( JitRegType<T>::Val_t , jit.getRegs( JitRegType<T>::Val_t , 1 ) ) );
}
private:
typedef std::map< Jit::RegType , int > MapRegType;
mutable MapRegType mapReg;
};
头文件中static const
是否正常,或者应该使用constexpr
?
有没有办法在Val_t
的类声明中声明JitRegType
但实际上没有定义它?
答案 0 :(得分:5)
按9.4.2p3:
如果非易失性 const static 数据成员是整数或枚举类型,则其在类定义中的声明可以指定 brace-or-equal-initializer [如果在程序中使用了odr,并且命名空间范围定义不包含初始值设定项,则仍应在命名空间范围内定义该成员。
所以你需要添加到你的程序中(可能在jit.cpp
中):
const Jit::RegType JitRegType<float>::Val_t;
这是因为如果在需要引用它的上下文中使用static const
成员,则链接器存在唯一的引用定义(与任何static
成员相同)这不是类模板或类模板部分特化的成员。)
深入探讨了这个问题on the gcc wiki。
请注意,gcc 4.6和4.7都表现得很合理;只是gcc 4.6选择内联JitRegType<float>::Val_t
的值,其中gcc 4.7选择不(或者可能是内联它,但也发出了对定义的链接器引用)。要判断执行是否需要执行诊断,这有点困难; 9.4.2p3描述了可诊断的规则,但随后9.4.2p4(隐式引用非const
static
数据成员)表示不需要诊断。无论哪种方式,作为实施质量问题,编译器发出诊断的好处都不是。