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
The issue here – albeit quite subtle – is that the
constexprusage error is not for the specifier on either theg()orh()functions (all that states is that it is possible for them to be compile-time evaluated). The error is on the specific line,constexpr int x = incr(k);in theg()function (for the reason given).In the
h()function, the analogous line doesn't have theconstexprspecifier … but that doesn't mean that it can't be evaluated at compile time. When callingh(1), the whole function can (and will) be evaluated at compile time, so there is noconstexprconflict.Change to using a call of
h(x)where the argument is not a literal (or other core constant expression) and you will see an error:From the same cppreference page that you linked (bold emphasis mine):