C++20 introduces the consteval
keyword, which enforces that a function is always evaluated at compile time.
constexpr
functions can produce a compile-time constant in some contexts and when called with appropriate arguments, but they can also
be invoked at run-time. consteval
functions must always be evaluated at compile-time. If that cannot happen, a compilation error will
occur.
User-defined literal operators are designed to be called with constant operands known at compile time. Therefore, if these are intended to be
evaluated at compile time with constexpr
, consteval
should be used instead to enforce compile time evaluation. This
guarantees that no code is evaluated at run-time, and also enables error detection at compile-time.
Noncompliant code example
constexpr unsigned char operator ""_u8(unsigned long long value) {
if (value >= 256u) { throw std::overflow_error("Overflow on literal"); }
return static_cast<unsigned char>(value);
}
void f() {
auto const a = 128_u8; // evaluated at compile time
auto const b = 512_u8; // evaluated at runtime, throws when evaluated
}
Compliant solution
consteval unsigned char operator ""_u8(unsigned long long value) {
if (value >= 256u) { throw std::overflow_error("Overflow on literal"); }
return static_cast<unsigned char>(value);
}
void f() {
auto const a = 128_u8; // evaluated at compile time
auto const b = 512_u8; // compilation error, the bug is detected
}