🔑Go deeper — read the bookC++ Keywords by Version — Specifiers & Attributes— runnable code & full walkthrough →

cpp20 · advanced

C++20 consteval & constinit — Compile-Time Guarantees

C++20 adds consteval and constinit to clarify compile-time guarantees. constexpr on a function means it CAN run at compile time but may also run at runtime — no guarantee. consteval makes a function an 'immediate function' that MUST be called with constant expressions; any runtime call is a compile error. Use consteval for hash functions, lookup table generation, or any computation that must be compile-time. constinit guarantees that a variable is initialized with a constant expression before any dynamic initialization runs; unlike constexpr, the variable is NOT const — it can be mutated after initialization. constinit fixes the Static Initialization Order Fiasco: a constinit global in TU-A is guaranteed to be set before any dynamic initialization in TU-B can reference it.

🔑 Key line

constexpr = may run at compile or runtime; consteval (C++20) = MUST run at compile time, runtime call is a compile error; constinit (C++20) = guaranteed compile-time initialization but mutable after — fixes SIOF on global variables.

The code

// constexpr — MAY run at compile or runtime
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr int a = factorial(5); // compile-time: a=120 in binary
int n = 7;
int b = factorial(n); // runtime: n not const, runs at runtime
// consteval — MUST run at compile time (C++20)
consteval int sq(int n) {
return n * n;
}
constexpr int x = sq(5); // OK: 5 is constant → compile time ✓
int y = 7;
// int z = sq(y); // ERROR: y is not constant expression
// constinit — initialize at compile time, but NOT const (C++20)
constinit int counter = 0; // guaranteed zero-initialized before any code runs
counter++; // mutable after init — constinit is about INIT only
// constinit fixes SIOF (Static Initialization Order Fiasco):
// constinit guarantees the variable is constant-initialized
// meaning it's set before dynamic initialization of any TU
constinit int config_id = computeId(); // computeId must be constexpr

What this lesson walks through

  1. 01Three keywords — three different guarantees
  2. 02constexpr — evaluated at compile time when possible
  3. 03constexpr with runtime argument — falls through to runtime
  4. 04consteval — immediate function, MUST be compile-time
  5. 05consteval with runtime arg — compile error enforced
  6. 06constinit — guaranteed compile-time initialization, but mutable
  7. 07constinit fixes the Static Initialization Order Fiasco

C++20 adds consteval and constinit alongside the existing constexpr. They look similar but give different guarantees: constexpr = may evaluate at compile OR runtime; consteval = MUST evaluate at compile time; constinit = MUST initialize at compile time but variable can mutate after.

See it animated — step by step, at your own pace

Unlock the full interactive walkthrough of C++20 consteval & constinit — Compile-Time Guarantees and 100+ animated C++ interview lessons.

← Previous
C++20 jthread & stop_token — RAII Threads with Cooperative Cancellation
Next →
C: String Literals — char* vs char[]