从GCC 4.6更改为4.7时未定义的参考

Undefined reference when changing from GCC 4.6 to 4.7

本文关键字:7时 未定义 参考 GCC      更新时间:2023-10-16

我不得不从g++-4.6切换到4.7(这样我就可以使用一些C++11特性)。现在,编译器抱怨道:

In function WordJIT<float>::WordJIT(): undefined reference to JitRegType<float>::Val_t

我想知道这些编译器版本之间是否发生了影响符号解析的变化。还是在新版本(4.7)中更好地实现了该语言,而我所做的是错误的:(相同的代码与4.6一起编译)

jit.h

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; };

wordjit.h

#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

有没有办法在JitRegType的类声明中也声明Val_t,但不实际定义它?

根据9.4.2p3:

如果非易失性const static数据成员是整型或枚举型,则其在类定义中的声明可以指定大括号或相等的初始值设定项〔…〕如果在程序中使用odr,则该成员仍应在命名空间作用域中定义,并且命名空间作用域定义不应包含初始值设定值。

所以你需要添加到你的程序中(可能在jit.cpp中):

const Jit::RegType JitRegType<float>::Val_t;

这样,如果static const成员在需要引用它的上下文中使用,则存在链接器引用的唯一定义(与任何不是类模板或类模板部分专用化成员的static成员相同)。

这个问题在gcc wiki上进行了深入讨论。

请注意,gcc 4.6和4.7都表现合理;只是gcc 4.6选择内联CCD_ 9的值,而gcc 4.7选择不内联(或者可能正在内联它。很难判断是否需要执行来发布诊断;9.4.2p3描述了可诊断规则,但9.4.2p4(隐含地指非conststatic数据成员)表示不需要诊断。不管怎样,作为一个实现质量问题,编译器发出诊断代码总比不发出要好。