Initialization order isn't really meaningful for anything that's constexpr
.
A constexpr
variable must be initialized by a constant expression, and since constant expressions don't have any side effects, and mutable global state isn't something that exists at compile time, you don't have to worry about initialization order.
If you want to get into the specifics:
Constant initialization is performed if a variable or temporary object with static or thread storage duration is constant-initialized ([expr.const]). [...]
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.
- https://eel.is/c++draft/basic.start.static#2
Initialization order for static initialization doesn't matter, because everything is being initialized to a compile-time constant. It's only an issue for dynamic initialization.
For constant initialization, the only thing that matters is the order of definition:
static constexpr int I1 = I + 1; // I1 defined before I2
static constexpr int I2 = I1 + 1; // I2 can use this definition
Any constexpr
variable, including static constexpr
data members must be initialized where they are defined.
Any constant expressions that appear further down in code then inevitably have that definition available, because the program is compiled from top to bottom.
In this example, it means that:
I1
must always be defined right where it's declared because it's constexpr
I2
always has this definition available, because it appears further down in the code