constinit specifier (since C++20) - cppreference.com (original) (raw)

[edit] Explanation

The constinit specifier declares a variable with static or thread storage duration.

If a variable is declared with constinit, its initializing declaration must be applied with constinit. If a variable declared with constinit has dynamic initialization (even if it is performed as static initialization), the program is ill-formed.

If no constinit declaration is reachable at the point of the initializing declaration, the program is ill-formed, no diagnostic required.

constinit cannot be used together with constexpr. When the declared variable is a reference, constinit is equivalent to constexpr. When the declared variable is an object, constexpr mandates that the object must have static initialization and constant destruction and makes the object const-qualified, however, constinit does not mandate constant destruction and const-qualification. As a result, an object of a type which has constexpr constructors and no constexpr destructor (e.g. std::shared_ptr<T>) might be declared with constinit but not constexpr.

const char* g() { return "dynamic initialization"; } constexpr const char* f(bool p) { return p ? "constant initializer" : g(); }   constinit const char* c = f(true); // OK // constinit const char* d = f(false); // error

constinit can also be used in a non-initializing declaration to tell the compiler that a thread_local variable is already initialized, reducing overhead that would otherwise be incurred by a hidden guard variable.

extern thread_local constinit int x; int f() { return x; } // no check of a guard variable needed

[edit] Notes

Feature-test macro Value Std Feature
__cpp_constinit 201907L (C++20) constinit

[edit] Keywords

constinit

[edit] Example

#include   constexpr int square(int i) { return i * i; }   int twice(int i) { return i + i; }   constinit int sq = square(2); // OK: initialization is done at compile time // constinit int x_x = twice(2); // Error: compile time initializer required   int square_4_gen() { static constinit int pow = square(4);   // constinit int prev = pow; // Error: constinit can only be applied to a // variable with static or thread storage duration int prev = pow; pow = pow * pow; return prev; }   int main() { assert(sq == 4); sq = twice(1); // Unlike constexpr this value can be changed later at runtime assert(sq == 2);   assert(square_4_gen() == 16); assert(square_4_gen() == 256); assert(square_4_gen() == 65536); }

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 2543 C++20 the behavior was unclear if the variable declared with constinitis dynamically initialized as part of static initialization the program is ill-formed in this case

[edit] See also