2

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ますが、実際には定義しませんか?

4

1 に答える 1

5

9.4.2p3 によると:

非揮発性const 静的データ メンバーが整数型または列挙型の場合、クラス定義でのその宣言は波括弧または等号初期化子を指定できます[...] メンバーは、それがプログラムで odr-used を使用し、名前空間スコープの定義には初期化子を含めないでください。

したがって、プログラムに追加する必要があります (おそらく でjit.cpp):

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

これは、メンバーへの参照が必要なコンテキストでメンバーが使用される場合、リンカーが参照する一意の定義が存在するようにするためです (クラス テンプレートまたはクラス テンプレート パーシャルのメンバーではないメンバーとstatic const同じです)。static専門)。

この問題については、gcc wikiで詳しく説明されています。

gcc 4.6 と 4.7 の両方が適切に動作していることに注意してください。gcc 4.6 が、gcc 4.7 が選択しない値をインライン化することを選択するだけですJitRegType<float>::Val_t(または、インライン化するが、定義へのリンカー参照も発行する可能性があります)。診断を発行するために実装が必要かどうかを判断するのは少し難しいです。9.4.2p3 は診断可能なルールを記述していますが、9.4.2p4 (非const staticデータメンバーを暗黙的に参照) は診断が不要であると述べています。いずれにせよ、実装の品質の問題として、コンパイラが診断を発行しないよりはましです。

于 2012-10-12T13:52:18.883 に答える