constexpr — C++

What is constexpr?

constexpr (C++11) tells the compiler to evaluate an expression at compile time if possible. It applies to variables and functions. C++20 added consteval (compile-time only) and constinit (constant initialization).


constexpr Variables

Must be initialized with a constant expression. Examples:

constexpr int max_size = 100;
constexpr double pi = 3.14159265358979;
constexpr int arr_size = max_size * 2; // composed constexpr

constexpr Functions

Can be evaluated at compile time (if all arguments are constant expressions) or at runtime (if not). C++11 had a strict single-return-statement rule; C++14 relaxed it; C++20 allows virtual functions.

constexpr int square(int x) { return x * x; }
constexpr int s = square(5);  // compile-time: s == 25
int n = 7;
int r = square(n);             // runtime evaluation

constexpr if (C++17)

if constexpr selects a branch at compile time based on a constant expression. The discarded branch is not instantiated — this enables generic code without SFINAE tricks.

template <typename T>
auto process(T val) {
    if constexpr (std::is_integral_v<T>) {
        return val * 2;
    } else {
        return val + 0.5;
    }
}

[!TIP] if constexpr replaces many SFINAE patterns and tag dispatch tricks that were common before C++17.


consteval (C++20)

Functions marked consteval are immediate functions — they MUST be called at compile time. A runtime call is a compile error.

consteval int triple(int x) { return x * 3; }
constexpr int t = triple(4);  // OK: compile-time
// int n = 5; triple(n);       // ERROR: n is not constexpr

constinit (C++20)

constinit ensures a variable is constant-initialized (initialized at program start, not at first use). It does NOT make the variable constant — the value can change later. Prevents the “static initialization order fiasco.”

constinit int global_counter = 0;   // constant-initialized
// global_counter = 42;              // OK: not const

[!WARNING] constinit only guarantees the initialization is constant - the variable itself is still mutable unless also declared const.


Keyword Overview

flowchart TD A[“constexpr (C++11)”] –> B[“constexpr variable”] A –> C[“constexpr function”] A –> D[“if constexpr (C++17)”] A –> E[“consteval (C++20)”] A –> F[“constinit (C++20)”]

constexpr Function Evaluation

flowchart TD A[“Call constexpr function”] –> B{“All args constant?”} B –>|”Yes”| C[“Compile-time evaluation”] B –>|”No”| D[“Runtime evaluation”] C –> E[“Result embedded in binary”] D –> F[“Result computed at runtime”]


Summary Table

KeywordC++ VersionPurposeRequirement
constexpr varC++11Compile-time constantMust be initialized with constant expression
constexpr fnC++11Compile-time or runtime evaluationBody must be constexpr-compatible
if constexprC++17Compile-time branch selectionCondition must be constant expression
constevalC++20Force compile-time evaluationCall site must be constant expression
constinitC++20Constant initialization guaranteeMust have constant initializer