从GCC 4.6更改为4.7时未定义的引用

时间:2012-10-12 13:10:54

标签: c++ static c++11 constants

我不得不从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

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

1 个答案:

答案 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数据成员)表示不需要诊断。无论哪种方式,作为实施质量问题,编译器发出诊断的好处都不是。