Today I learned that in C++, constant evaluation does not permit operations that would have undefined behavior. For example, the following code will not compile in a constexpr context because it reads from the inactive member of a union:
union U {
int i;
double d;
};
constexpr double f() {
U u;
u.i = 42;
return u.d; // undefined behavior: reading from the currently inactive union member
}
int main() {
constexpr double x = f(); // error: not a constant expression
}Interestingly, the same function can still be called in a non-constexpr runtime context:
int main() {
double y = f(); // well-formed, but executing this call has undefined behavior at runtime
}constexpr specifier is just a hint to the compiler that a function may be evaluated at compile time.If we change the function to consteval:
consteval double f() {
U u;
u.i = 42;
return u.d; // undefined behavior: reading from the currently inactive union member
}consteval functions must always be evaluated at compile time.constexpr evaluation can catch undefined behavior at compile time, which can help avoid runtime issues. This is especially useful in scenarios where performance and correctness are critical.
With the introduction of consteval in C++20, we can enforce that certain functions are always evaluated at compile time, which helps ensure that this kind of issue is caught early in the development process.
“Live as if you were to die tomorrow. Learn as if you were to live forever.” - Mahatma Gandhi