如何定义一个 constexpr 构造数组,该数组在多个翻译单元上只有一个实例?

Adr*_*ian 2 c++ constexpr c++14

我正在生成constexpr std::array一个类的内部constexpr,但我只想在使用该类的所有项目中使用该类的一个实例。

我最初将其设为全局变量,但后来发现,如果我在多个翻译单元中迭代数组,这些全局变量就会重复。然后我尝试使用一个constexpr函数,但我无法拥有static这样一个函数的内部。我使用的是c++14,所以我不能使用变量inline constexpr。变量extern constexpr没有意义,因为如果将声明与定义分开,那么constexpr当只需要一项时,如何以编译时而不是运行时的方式处理这些值?

还有其他选择吗?

编辑:参见https://godbolt.org/z/5PcboYov4

请记住,我没有定义常规变量。我正在定义一个constexpr变量。区别很重要。它被用于非上下文constexprconstexpr上下文中。

use*_*522 5

变量模板具有外部链接,即使它们是const- 限定的:

template<typename = void>
constexpr std::array my_array{/*...*/};

// use my_array<> to access the array.
Run Code Online (Sandbox Code Playgroud)

然而,这只是从DR 2387开始,我想这也应该适用于 C++14,尽管它直到 2019 年才得到解决。

如果编译器没有实现它,那么你可以extern显式添加。据我所知,这是允许的,并且声明仍然是一个定义,因为它有一个初始值设定项。因为它是一个模板,所以多个定义不存在 ODR 违规:

template<typename = void>
extern constexpr std::array my_array{/*...*/};

// use my_array<> to access the array.
Run Code Online (Sandbox Code Playgroud)

由于某种原因,我忘记了使用静态数据成员的最明显的解决方法:

struct my_array_wrapper {
    static constexpr std::array</*...*/> my_array{/*...*/};
};

// in one translation unit
constexpr std::array</*...*/> my_array_wrapper::my_array;
Run Code Online (Sandbox Code Playgroud)

然后就my_array_wrapper::my_array可以使用了。如果仅在 C++17 之前使用 ODR 数组,则需要翻译单元中的定义。具有外部链接的类中的静态数据成员也具有外部链接,无论它们是否具有const- 限定。