The statement auto square1 = initialize a global variable, not even constant. This is a runtime variable that you can mutate, assign to and potentially other stuff.
You could very well initialize such variable like this:
auto returnMeALambda() { int capture = rand() % 2; return [capture](auto val) { return val * val + capture; } } auto square1 = returnMeALambda();
As you can see, the code of returnMeALambda is strictly runtime, so square1 is forcibly initialized at runtime.
Those variables don't have a value that it usable at compile time. The compiler might very well initialize it at runtime, even if not forced to. This has cost at runtime, and with the static initialization order fiasco, you could technically use the lambda before it is initialized, or even use another global before it is initialized:
extern int baseval; auto returnMeALambda() { int capture = baseval + rand() % 2; return [capture](auto val) { return val * val + capture; } } auto square1 = returnMeALambda(); int baseval = square1(2);
This code will always end up being undefined behaviour since it always use an uninitialized variable, no matter the initialization order.
The solution proposed by the author is to initialize the variable as a constexpr. This do three things in this case:
- Makes the variable
const. You cannot mutate its value at runtime. - Constant initialization is now mandated. The value of
square1 is encoded in the executable binary code. - Makes the variable value available at compile time. You can now use the variable in constexpr context.
The second point is the property the author seek as a solution. The variable is guaranteed it won't ever be initialized at runtime, since the value is available at compile time and guarantees constant initialization by the compiler.
Note that in C++20 you can apply the second point by itself without forcing the value to be const using constinit.
constinit int value = 9;
Now the compiler is forced to initialize the value using constant initialization, but also the variable is mutable at runtime. This effectively solve the initialization order fiasco given you can constant initialize your variables.
auto squared1might be computed at compile time. Or not. No guarantees. Addingconstexprprovides that guarantee.