I am reading an example of cppreference at https://en.cppreference.com/w/cpp/language/constant_expression
Specifically, this one:
constexpr int incr(int& n)
{
return ++n;
}
constexpr int g(int k)
{
constexpr int x = incr(k); // error: incr(k) is not a core constant
// expression because lifetime of k
// began outside the expression incr(k)
return x;
}
constexpr int h(int k)
{
int x = incr(k); // OK: x is not required to be initialized
// with a core constant expression
return x;
}
constexpr int y = h(1); // OK: initializes y with the value 2
// h(1) is a core constant expression because
// the lifetime of k begins inside the expression h(1)
So, as far as I can tell, the issue with this code:
constexpr int x = incr(k);
is that it goes against this core expression rule: "modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression".
But why does this instead work, even if the compiler evaluates it at compile-time the same way? (We can check this with std::is_constant_evaluated()
)
Isn't the compiler going against the "core expression rules" by evaluating this at compile time anyway?
int x = incr(k); // k lifetime didn't start in this expression, so incr should not be able to mutate it since the "core constant expression" rules disallow it