Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the initialization order of constexpr (i.e. constant-initialized) template variables guaranteed?

From en.cppreference.com/w/cpp/language/initialization:

Unordered dynamic initialization, which [sic] applies only to (static/thread-local) class template static data members and variable templates (since C++14) that aren't explicitly specialized.

Therefore static templates appear to be vulnerable to an even worse version of The Static Initialization Order Fiasco (TSIOF) (i.e. unordered within a translation unit).

Does use of constexpr remove this vulnerability?

i.e. is the output of the below code guaranteed to be success?

Obviously, due to the nature of this question, working examples won't suffice as answers; quotes from the standard would be required. (C++17 answers preferred)

#include<cassert>

template<class T> static constexpr T a = 41;
template<class T> static constexpr T b = a<T>+1;
int main(){
    assert(b<int> == 42);
    std::cout <<"success\n";
}

BTW, if someone is an expert on this I have a related, unanswered question (that would be easy for such an expert to answer) here. Further, what would be the implications here if the answer to my other question is negative (i.e. constexpr doesn't help across translation units)?

UPDATE: I need to clarify what my concern is here. The original question title asked whether initialization order is a concern for constexpr template variables. I have clarified it. I am not concerned about whether dynamic initialization is taking place in the example; it isn't. My concern is that since ordered initialization cannot be assumed in the dynamic initialization case, can it be assumed in the constant initialization case? Prior to seeing the behavior of dynamically initialized template variables (within the same translation unit) I would have never even thought of this. However, since dynamically-initialized, static-duration template variables do not provide ordered initialization I now see no reason to assume that constant-initiliazed, static-duration template variables have guaranteed ordered initialization either. I need to be 100% sure that constant initialization of template variables takes place in the order of their definition within a TU.

Again, I see no reason to assume the constant-initializer-within-the-compiler is required to intialize in order if the dynamic initializer isn't. Absence of a warning in the standard that constant initialization is unordered does not suffice.

I realize that some may think this is excessive concern but I am working on safety-critical software and my company has placed adoption of C++14 on hold until this issue is resolved.

like image 631
Lotney Avatar asked May 17 '18 22:05

Lotney


People also ask

What is the order of static variable initialization across one program?

Within a single compilation unit, static variables are initialized in the same order as they are defined in the source (this is called Ordered Dynamic Initialization). Across compilation units, however, the order is undefined: you don't know if a static variable defined in a.

Are static variables initialized to zero in c++?

Global and static variables are initialized to their default values because it is in the C or C++ standards and it is free to assign a value by zero at compile time. Both static and global variable behave same to the generated object code. These variables are allocated in .

How to initialise static variable c++?

For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value.


1 Answers

Based on basic.start.static:

Constant initialization is performed if a variable or temporary object with static or thread storage duration is initialized by a constant initializer for the entity.

In your code:

template<class T> static constexpr T a = 41; // constant initialization

is doing constant initialization which makes:

template<class T> static constexpr T b = a<T>+1;

be initialized with 42 due to the templates' constant evaluation.

which states that (From expr.const/8.7):

a variable whose name appears as a potentially constant evaluated expression that is either a constexpr variable or is of non-volatile const-qualified integral type or of reference type.

Thus, it is guaranteed the output is always "success"ful.

NOTE From basic.start.static/2:

Together, zero-initialization and constant initialization are called static initialization

-- not dynamic initialization

like image 77
Joseph D. Avatar answered Sep 27 '22 20:09

Joseph D.