Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

global initialization order with constexpr

Let's consider this hunk of code that simply tries to initialize a map from a constexpr array:

#include <string>
#include <map>
#include <array>
#include <tuple>

constexpr std::array<std::pair<int, const char *>, 10> my_array {
    { { 0, "dd" },
    { 1, "dd" },
    { 2, "dd" },
    { 7, "dd" },
    { 8, "dd" },
    { 9, "dd" }}
   };

std::map<int, std::string> my_map(std::begin(my_array), std::end(my_array));

int main() {
    return my_map[0].size(); //dummy random operation
}

I know there is not way to predict initialization order for the two variables (my_array and my_map). That said, my_array is constexpr, thus should be available a compile time, thus there should be no "initialization order" problem at startup.

Is this code correct or does the initialization order problem remains?

like image 345
OznOg Avatar asked Oct 06 '19 18:10

OznOg


People also ask

What is the use of constexpr in C++?

constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.

Should constexpr be static?

The short answer is that not only is static useful, it is pretty well always going to be desired. First, note that static and constexpr are completely independent of each other. static defines the object's lifetime during execution; constexpr specifies that the object should be available during compilation.

Why does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Is static constexpr redundant?

Pretty much redundant; constexpr variables have internal linkage per default.


1 Answers

[basic.start.static/2]:

Constant initialization is performed if a variable or temporary object with static or thread storage duration is constant-initialized. [...] Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. All static initialization strongly happens before ([intro.races]) any dynamic initialization.

So, "Is this code correct?": Yes, as my_array is constant initialized, and this happens before dynamic initialization (my_map).

(This quote is from the current draft standard, but this rule exists for C++14 as well)

like image 90
geza Avatar answered Oct 17 '22 17:10

geza