It's impossible to detect if something was evaluated at runtime or compile-time using only the C++ itself, so the as-if rule allows the compiler to do whatever it wants.
Nothing stops a compiler from performing the addition in your macro at runtime, and nothing stops it from calculating even a non-constexpr
function at compile-time (as long as it doesn't perform any IO, etc). It all depends on optimization settings and the sanity of the compiler.
Normally, in unoptimized builds, constexpr
functions are executed at runtime unless the return value is used in a context that requires a compile-time constant. This includes initializing a constexpr
variable from it, and your const int res2
implicitly becomes constexpr
because its initializer is constexpr
, so foo(5)
should be called at compile-time.
In optimized builds, you can expect the compiler to do as much as possible at compile-time. (A function doesn't even have constexpr
, as long as the function body is visible in the current translation unit, or if link-time optimizations are enabled.)