Fadli Arsani
↑↓ to navigate · Enter to open · Esc to close

if consteval

if consteval checks whether the current evaluation context is a manifestly constant-evaluated context, meaning a context where the compiler is required to produce a compile-time constant (e.g., initializing a constexpr variable, evaluating a static_assert, or computing a template argument). It was added in C++23 and formally called a consteval if statement: “The statement that begins with if consteval is known as the consteval if statement…”. This makes it useful inside constexpr functions, functions that live a double life (compile time and runtime), where you want different implementations for each:

constexpr int fast_sqrt(int n) {
    if consteval {
        // compile-time: must be constexpr-friendly, no intrinsics
        int i = 0;
        while (i * i <= n) ++i;
        return i - 1;
    } else {
        // runtime: use optimized hardware path
        return static_cast<int>(__builtin_sqrt(n));
    }
}

constexpr int x = fast_sqrt(49); invokes the if consteval branch. int x = fast_sqrt(n); with a runtime n takes the else branch.

Note that if consteval takes no condition. It does not test whether a specific expression is a compile-time constant. To verify that, use static_assert or assign to a constexpr variable instead.

template<int N>
struct square : std::integral_constant<int, N * N> {};

template<int N>
inline constexpr int square_v = square<N>::value;

// wrong: if consteval doesn't take an expression
if consteval (square_v<23>) { }

// do this instead
static_assert(square_v<23> == 529);
// or this
constexpr int x = square_v<23>;