模板中的 C++ 静态常量初始化顺序

标签 c++ static initialization c++14 constants

冒着被标记为重复的风险,我捕获了机会。 请考虑以下事项:

给定以下静态常量数组 arrA 和 arrB,arrB 取决于 arrA。

#include <iostream>
#include <string>
#include <array>

template<int N>
class MyClass {
public:
    static const std::array< int, N> arrA;
    static const std::array< int, N> arrB;
};

template<int N>
std::array<int, N> const MyClass<N>::arrA = []() -> decltype(auto) {
    std::array<int, N> arr;
    for (int i = 0; i < N; i++) {
        arr[i] = 1 + i;
    }
    return arr;
} ();

template<int N>
std::array<int, N> const MyClass<N>::arrB = []() -> decltype(auto) {
    std::array<int, N> arr;
    for (int i = 0; i < N; i++) {
        arr[i] = arrA[i] + 1;
    }
    return arr;
} ();


int main()
{
    constexpr int i = 3;
    std::cout << std::to_string(MyClass<i>::arrB[0]) << std::endl;
}

如果我没理解错,这是标准中给出的静态常量成员无序初始化的情况:

1) Unordered dynamic initialization, which applies only to (static/thread-local) class template static data members and variable templates (since C++14) that aren't explicitly specialized. Initialization of such static variables is indeterminately sequenced with respect to all other dynamic initialization except if the program starts a thread before a variable is initialized, in which case its initialization is unsequenced (since C++17). Initialization of such thread-local variables is unsequenced with respect to all other dynamic initialization.

我能找到的最佳答案是 here但没有提及是否存在允许以有序方式执行此类初始化的已知模式。在保持 static const 的同时是否有可能?

理想情况下,我希望数组保持 const , 否则问题是微不足道的。

虽然这个例子可以用 constexpr 构建,在实际情况下需要动态初始化(我使用 <random> )。

编辑:我觉得有趣的是,无论源代码中声明或定义的顺序如何,arrBarrA 之前初始化.

最佳答案

如果你想保证初始化的顺序,你必须将两个数组包装在一个结构中,并使用结构的构造函数来初始化静态变量。 Here是我的意思的一个例子。

#include <iostream>

template <typename T>
struct A {
    struct B {
        B() : c(0), d(c + 1) {}
        T c;
        T d;
    };
    static B b;

    static T& c() {
        return b.c;
    }

    static T& d() {
        return b.d;
    }
};

template <typename T>
typename A<T>::B A<T>::b{};

int main() {
    std::cout << A<int>::b.c << ", " << A<int>::b.d << std::endl;
    std::cout << A<int>::c() << ", " << A<int>::d() << std::endl;
    return 0;
}

如果你这样做,你可能想要提供访问器,例如 (c()d()) - 你也可以使用结构访问器的结果是私有(private)的和常量的,所以,例如,你可以这样做

template <typename T>
struct A {
    static const T& c() {
        return b.c;
    }

    static T& d() {
        return b.d;
    }

    private:   
    struct B {
        B() : c(0), d(c + 1) {}
        T c;
        T d;
    };
    static B b;
};

关于模板中的 C++ 静态常量初始化顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61887372/

相关文章:

python - 在 Python 中管理实例

c++ - 为什么 GLU 会在这个地方崩溃?

c++11 多个定义未使用 odr?

c++ - 如何调试boost archive异常输入流错误

javascript - 如何从 Django 加载模型管理文件中的静态文件?

c++ - 类初始化中的静态 lambda

c++ - 在多个源/头文件中使用 c++ 类时的头文件设置

java - 为什么在静态上下文中访问实例化字段比在 JAVA 中访问实例化上下文更快

c++ - C++中类或结构的常量静态成员变量不需要单独定义吗?

javascript - RequireJS - 首先初始化一个依赖模块,然后再加载其他模块