I have made a thread yesterday but I think that it was unclear and the replies I got didn't solve my confusion at all. So, I'll try to make the example simpler.
Why is this allowed:
constexpr int incr(int k1)
{
return k1 + 5;
}
constexpr int foo(int k) // runs in compile time
{
return incr(k);
}
int main() {
constexpr int x = 5;
constexpr int y = foo(4);
}
... But this very similar function is not?
constexpr int incr(int k1)
{
return k1 + 5;
}
constexpr int foo(int k) // runs in compile time
{
constexpr int x = incr(k); // k: not a constant expression
return x;
}
int main() {
constexpr int x = 5;
constexpr int y = foo(4);
}
How exactly are these two functions different in the context of constant evaluation? To me they look almost exactly the same, except one returns instantly while the other first computes the value and assigns it to the constexpr variable.
If you can, please also refer to the standard so that I can read further!
The rule about
constexprvariables is [dcl.constexpr]/6,Every constant expression must be a core constant expression, with some additional restrictions that are not relevant here, so I won't get into them ([expr.const]/13). If the initialization of a
constexprvariable is not a core constant expression, the program is ill-formed.The particular rule violated by the second example is [expr.const]/5.9.
In the declaration
the full-expression "initialize an
intvariable fromincr(k)" fails to be a core constant expression because, when it is evaluated, it needs to perform an lvalue-to-rvalue conversion onkin order to get the value to initializek1with. The variablekis not usable in constant expressions, nor did its lifetime begin within the full-expression "initialize anintvariable fromincr(k)".In the first example, which your compiler accepts,
incr(k)is also being evaluated at compile time, but it is not required to be a core constant expression, so there is no problem. It's very confusing at first, but we need to remember that something that is not a core constant expression can be evaluated as part of a "bigger" evaluation that is a core constant expression. In this case, it is the enclosingconstexprvariable initialization (that ofy) that is required to be a core constant expression—and it is, because it creates the function parameterk(initializing it with the value 4) and then reads from it. To put it another way, if E is "initializeywithfoo(4)", then the lifetime ofkbegins within E, so the read ofkcan occur without preventing E from being a core constant expression.