使用静态成员初始化静态映射

时间:2016-06-13 13:43:32

标签: c++ c++11 dictionary static

尝试初始化静态地图。从其他问题我收集到它必须在头文件之外完成,并且在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

3 个答案:

答案 0 :(得分: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'
}

这是因为绑定引用是i的{​​{3}},这需要在链接时存在唯一的定义。

有一个简单的解决方法适用于大多数此类情况,即应用一元+

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

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

应用+并非ODR使用i,因为只需要其值,而不是其身份。然后引用绑定到+返回的临时值,而不是i

答案 1 :(得分:3)

您还需要定义TestSuite::x。把它放在你的cpp文件中:

const int TestSuite::x;

答案 2 :(得分: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}};