2016-06-13 115 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}};