简体   繁体   English

C++ Static 模板中的 const 初始化顺序

[英]C++ Static const initialization order in templates

Risking getting flagged for duplication, I take my chances.冒着被标记为重复的风险,我抓住了机会。 Consider the following:考虑以下:

Given the following static const arrays arrA and arrB, arrB depending on arrA.给定以下 static const arrays 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;
}

If I understand correctly, this is a case of unordered initialization of static const member as given in the standard:如果我理解正确,这是标准中给出的 static const 成员无序初始化的情况:

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. 1) 无序动态初始化,仅适用于未明确专门化的(静态/线程局部)class 模板 static 数据成员和变量模板(C++14 起)。 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).此类 static 变量的初始化相对于所有其他动态初始化是不确定的,除非程序在变量初始化之前启动线程,在这种情况下,它的初始化是无序的(C++17 起)。 Initialization of such thread-local variables is unsequenced with respect to all other dynamic initialization.相对于所有其他动态初始化,此类线程局部变量的初始化是无序的。

The best answer I could find is here but makes no mention of whether there's a known pattern allowing to perform such initialization in an ordered way.我能找到的最佳答案是here,但没有提及是否存在允许以有序方式执行此类初始化的已知模式。 Is that even possible while keeping static const ?在保持static const的同时,这是否可能?

Ideally I'd like the arrays to remain const , otherwise the problem is trivial.理想情况下,我希望 arrays 保持const ,否则问题是微不足道的。

Though this example could be built with constexpr , in a real-world case dynamic initialization is required (I use <random> ).尽管可以使用constexpr构建此示例,但在实际情况下需要动态初始化(我使用<random> )。

Edit: I find it interesting that no matter the order of declaration or definition in the source, arrB gets initialized before arrA .编辑:我发现有趣的是,无论源中的声明或定义顺序如何, arrBarrA之前被初始化。

If you want to guarantee the order of initialisation you have to wrap both arrays in a struct and use the struct's constructor to initialise the static variable.如果要保证初始化顺序,则必须将 arrays 包装在一个结构中,并使用该结构的构造函数来初始化 static 变量。 Here is an example of what I mean.是我的意思的一个例子。

#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;
}

If you do this you might want to provide accessors, as for the example ( c() and d() ) - you can also play around with the struct being private and with constness for the result of the accessors, so, for example, you can do如果您这样做,您可能希望提供访问器,例如示例( c()d() ) - 您还可以使用私有结构和访问器结果的常量,例如,你可以做

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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM