2016-06-13 117 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重現此問題。但是,它可以被複制,你嘗試綁定到一個constexpr變量的引用您還沒有定義,這是你的std::map構造函數可能就是任何時候:

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

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

這是因爲綁定引用的ODR-usei,它需要在鏈接時存在唯一的定義。

有一個簡單的解決方法是,在大多數這樣的情況下工作,這是應用一元+

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