constexpr Functions: Optimization vs Guarantee -- Andreas Fertig
Constexpr has been around for a while now, but many don’t fully understand its subtleties. Andreas Fertig explores its use and when a constexpr expression might not be evaluated at compile time.
constexpr Functions: Optimization vs Guarantee
by Andreas Fertig
From the article:
The feature of constant evaluation is nothing new in 2023. You have constexpr available since C++11. Yet, in many of my classes, I see that people still struggle with
constexpr
functions. Let me shed some light on them.What you get is not what you see
One thing, which is a feature, is that
constexpr
functions can be evaluated at compile-time, but they can run at run-time as well. That evaluation at compile-time requires all values known at compile-time is reasonable. But I often see that the assumption is once all values for aconstexpr
function are known at compile-time, the function will be evaluated at compile-time.I can say that I find this assumption reasonable, and discovering the truth isn’t easy. Let’s consider an example (Listing 1).
constexpr auto Fun(int v) { return 42 / v; ① } int main() { const auto f = Fun(6); ② return f; ③ }Listing 1 The
constexpr
functionFun
divides 42 by a value provided by the parameterv
①. In ②, I callFun
with the value6
and assign the result to the variablef
.Last, in ③, I return the value of
f
to prevent the compiler optimizes this program away. If you use Compiler Explorer to look at the resulting assembly, GCC with-O1
brings this down to:main: mov eax, 7 retAs you can see, the compiler has evaluated the result of 42 / 6, which, of course, is 7. Aside from the final number, there is also no trace at all of the function
Fun
.Now, this is what, in my experience, makes people believe that
Fun
was evaluated at compile-time thanks toconstexpr
. Yet this view is incorrect. You are looking at compiler optimization, something different fromconstexpr
functions.