Table of contents
constexpr
C++11 introduced constexpr
specifier that enables the computation of functions and variables at compile time. Functions with known inputs are evaluated, and their return values are included in the final code, reducing its size.
However, please note that the compiler may still embed this function to be executed at runtime, generating the machine code for it.
Generated machine code
To understand the implications of using constexpr on machine code generation, let’s understand the various scenarios outlined below.
Function with no specifier
This is any normal function and its associated assembly code. We can see the square
function is part of the machine code (line 1-8
) on the right-hand side.
Function with constexpr specifier
Merely specifying constexpr
won’t change the generated machine code.
With constexpr inputs
Finally, when we mark the input parameters as well as a constexpr
, the square
function is evaluated at compile time, and no machine code is generated for it.
consteval
C++20 introduced consteval
specifier that ensures the computation of functions at compile time. The consteval
specifier for a function makes it mandatory to have all the inputs also marked as constexpr
Generated machine code
With calling the function without constexpr inputs
The compiler flags an error when a function marked with consteval
is invoked with non-constant values.
With calling the function with constexpr inputs
When all the requirements are satisfied, we see the evaluation happening during the compile time, and no machine code gets generated for the function.
constexpr vs consteval: a comparison
All of the above screenshots are taken from this Godbolt example!
Conclusion
This article outlines the subtle differences between the specifiers constexpr
and consteval
along with machine codes. The following are the key takeaways from these, and in the next article, I will share how to use these in production code.