类模板(C++17)中静态内联成员变量的初始化顺序



我正在编写一个代码,其中我需要使用类模板实例的静态变量初始化某个类的静态成员变量。我知道静态初始化顺序的失败,并找到了几个关于这个问题的讨论,但没有一个真正帮助我解决问题。我甚至不知道为什么这会成为我的问题。

这是一个最小的例子,再现了我从代码中得到的错误:

#include <string>
#include <map>

template<class T>
class Foo {
private:
static inline std::map<std::string, T> map_ = {};

public:

static bool insert(const std::string& key, T value) {
map_[key] = value;
return true;
}
};

using MyFoo = Foo<char>;
class Bar {
static inline bool baz_ = MyFoo::insert("baz", 'A');
};

int main() {
// This works just fine if the definition of Bar::baz_ in line 24 is removed
//MyFoo::insert("baz", 'A');
return 0;
}

使用C++17标准的编译以0个警告和0个错误结束。然而,在执行程序时,调用Foo::insert时会出现分段故障。此时Foo::map_似乎未初始化。但是,静态变量不应该按照代码中定义的顺序初始化吗?

我还应该提到,没有模板的代码运行良好。所以我想知道编译器是否以在Bar之后定义实际类的方式实例化模板。可能是这样的问题,还是编译器在这种情况下碰巧做了"正确"的事情?

类模板专门化的静态数据成员的动态初始化(如果它们没有显式专门化(与任何其他动态初始化完全无序(不确定顺序(。成员是否为inline并不重要,其他动态初始化是否也是类模板专业化的静态数据成员也不重要,静态数据成员的实例化点和定义点在翻译单元中的位置也不重要。

因此,无法保证CCD_ 5在CCD_ 6之前被初始化。

相反,请使用常见的习惯用法,即使用包含静态成员的静态成员函数作为本地static变量:

static auto& map_() {
static std::map<std::string, T> map = {};
return map;
}
// replace `map_` with `map_()` everywhere else

最新更新