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

rit*_*ter 2 c++ static constants c++11

我不得不从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; };
Run Code Online (Sandbox Code Playgroud)

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;
  };
Run Code Online (Sandbox Code Playgroud)

编辑:

static const在头文件正确的,或者应该使用一个constexpr

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

eca*_*mur 5

按9.4.2p3:

如果非易失性const静态数据成员是整数或枚举类型,则它在类定义中的声明可以指定一个大括号或者等于初始化程序 [...]如果成员仍然是在命名空间作用域中定义的程序中使用的odr和命名空间范围定义不应包含初始化程序.

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

const Jit::RegType JitRegType<float>::Val_t;
Run Code Online (Sandbox Code Playgroud)

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

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

请注意,gcc 4.6和4.7都表现得很合理; 只是gcc 4.6选择内联JitRegType<float>::Val_tgcc 4.7选择的值不是(或者可能是内联它,但也发出了对定义的链接器引用).要判断执行是否需要执行诊断,这有点困难; 9.4.2p3描述了可诊断的规则,但随后9.4.2p4(隐含地指非const static数据成员)表示不需要诊断.无论哪种方式,作为实施质量问题,编译器发布诊断比不是更好.