[英]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
.编辑:我发现有趣的是,无论源中的声明或定义顺序如何, arrB
在arrA
之前被初始化。
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.