I know about the problem of the order of initialization of static variables from different translation units. However, my problem is within one translation unit and, in fact, within one struct:
template <int size>
struct SlidingTile {
using AllActions = std::array<int, size>;
using AllMDDeltas = std::array<int, size>;
int mdDelta(int i) const {
return mdDeltas_[i];
}
static AllActions computeAllActions() {
std::cout << "computeAllActions" << std::endl;
AllActions res;
for (int i = 0; i < size; ++i) res[i] = i;
return res;
}
static AllMDDeltas computeAllMDDeltas() {
std::cout << "Entered computeAllMDDeltas" << std::endl;
AllActions res;
for (int i = 0; i < size; ++i) res[i] = 10 * allActions_[i];
std::cout << "Exiting computeAllMDDeltas" << std::endl;
return res;
}
private:
static const AllActions allActions_;
static const AllMDDeltas mdDeltas_;
};
template <int size>
const typename SlidingTile<size>::AllActions
SlidingTile<size>::allActions_ = SlidingTile<size>::computeAllActions();
template <int size>
const typename SlidingTile<size>::AllMDDeltas
SlidingTile<size>::mdDeltas_ = SlidingTile<size>::computeAllMDDeltas();
int main() {
SlidingTile<3> s;
std::cout << s.mdDelta(2) << std::endl;
return 0;
}
The output is:
Entered computeAllMDDeltas
Exiting computeAllMDDeltas
computeAllActions
To my surprise, computeAllMDDeltas
gets called before computeAllActions
and so allActions_
is not initialized when it is used in computeAllMDDeltas
. Interestingly, computeAllActions
is not called even when allActions_
is used in computeAllMDDeltas
.
Why does this happen and what is the advised way in this situation?
How come the definition order is not followed when defining static member variables?
Because the standard says that the initialization is unordered:
[basic.start.init] /2 (N4140 standard draft)
... Definitions of explicitly specialized class template static data members have ordered initialization. Other class template static data members (i.e., implicitly or explicitly instantiated specializations) have unordered initialization. ...
what is the advised way in this situation?
Same as initialization across translation units: Construct On First Use idiom:
struct SlidingTile {
// ...
private:
static const AllActions& allActions() {
static const AllActions instance = computeAllActions();
return instance;
}
static const AllMDDeltas& mdDeltas() {
static const AllMDDeltas instance = computeAllMDDeltas();
return instance;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With