2016-06-13 8 views
3

静的マップを初期化しようとしています。私が収集した他の質問からは、ヘッダーファイルの外側で行う必要があり、C++ 11では一様な初期化を行うことができます。私は別の静的メンバを使用しようとする。しかし、私は問題を得る:静的メンバーを使用して静的マップを初期化する

がfoo.h:

#include <map> 

class TestSuite { 
    static constexpr int x = 3; 
    static std::map<int, int> v; 
}; 

foo.cpp:次に

#include "foo.h" 

std::map<int, int> TestSuite::v = {{x, 5}}; 

int main() { 
    TestSuite t; 
} 

私はエラーに取得

In function `__static_initialization_and_destruction_0(int, int)': 
foo.cpp:(.text+0x4b): undefined reference to `TestSuite::x' 
collect2: error: ld returned 1 exit status 
+1

はうまくいくようですが、どのコンパイラを使用しますか? – IceFire

+0

5.2、6.1の新機能でなければならない – acornellier

答えて

4

私はGCC 6.1.0でこの問題を再現することはできません。しかし、あなたがあなたのstd::mapコンストラクタが何おそらくあなたが定義されていないconstexpr変数への参照をバインドしようとする任意の時間を再現することができます:

struct Foo { 
    static constexpr int i = 42; 
}; 

int main() { 
    auto const &p = Foo::i; // undefined reference to `Foo::i' 
} 

参照を結合することのODR-useあるためですi。リンク時に一意の定義が存在する必要があります。

あり、ほとんどそのような場合に動作します簡単な回避策があり、それは単項+を適用することです:

struct Foo { 
    static constexpr int i = 42; 
}; 

int main() { 
    auto const &p = +Foo::i; // OK! 
} 

のみ、その値が必要とされているので+を適用するODR-使用が、iないありません身元。次に、iではなく、+によって返された一時的な値に参照がバインドされます。

+0

参照:http://stackoverflow.com/a/372​​59949/3903076 – filipos

3

また、TestSuite::xを定義する必要があります。これをあなたのcppファイルに入れてください:

const int TestSuite::x; 
+0

静的初期化命令の失敗はまったく問題になりますか? – NathanOliver

+2

@ NathanOliver両方が同じTUにある場合、初期化の順序は明確に定義されています。 –

1

もうひとつの解決策です。

staticメンバ変数をstaticメンバ関数に変更します。

class TestSuite { 
    static constexpr int getX() { return 3;} 
    static std::map<int, int> v; 
}; 

std::map<int, int> TestSuite::v = {{getX(), 5}}; 
関連する問題