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
}