what situation will the evaluation for expressions occur in

Viewed 132
constexpr int func(int rf){
    constexpr int  v = rf;  // #1
    return 0;
}
int main(){
}

Consider the above code, the compiler complains such a code is ill-formed. The outcome is here:

error: 'rf' is not a constant expression

That is said, the expression at the place that marked with #1 is evaluated by the compiler. I agree that rf is not a constant expression, because it does violate the following rules:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:
expr.const#2

an lvalue-to-rvalue conversion unless it is applied to

  • a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression, or
  • a non-volatile glvalue that refers to a subobject of a string literal, or
  • a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable subobject of such an object, or
  • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

However, what makes me confused is, I didn't call function func anywhere in my example, why the compiler evaluate the expression rf? That makes me don't understand what is evaluation and what is the execution.

According to this rule:
intro.execution#18

When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. For each function invocation F, for every evaluation A that occurs within F and every evaluation B that does not occur within F but is evaluated on the same thread and as part of the same signal handler (if any), either A is sequenced before B or B is sequenced before A.

It sounds like that, only if the corresponding function is called, then the evaluation for expression which is in the function body does occur.

However, Obviously I didn't call func in my example. So, my questions are:

Question 1:

what situation will the evaluation for expressions occur in?
For constant expressions, there is only a crude tip in the standard, that is, [Note: Constant expressions can be evaluated during translation. — end note], there's no more.

Question 2:

As a contrast, If the statement at #1 would be int v = rf;, Does the compiler evaluate such an expression rf during translation if I don't call function func?

Question 3:

what's the difference between evaluation and execution?

Question 4:

where's the relevant clause in the standard specified what situation the evaluation for expressions will occur in?

2 Answers

I will assume that you already know that, the full-expression of the initialization of a constexpr variable V has to be a constant expression ([dcl.constexpr]/10) so that the compiler, at compile-time, can replace each occurrence of expression V with its corresponding value.

And in order to know whether an expression is a constant expression, you have to firstly know whether the expression is a core constant expression. The standard has a whole subclause described in [expr.const] defines how to know whether an expression is a core constant expression.

From my point of view, any expression E is a core constant expression unless E evaluates any of the constraints in [expr.const]/5.

Considering what has been said, since your variable v is a constexpr, its initializer (rf in this case) has to be a constant expression. Ask yourself first: Is rf a core constant expression? To know that, ask yourself again: Is rf evaluates any of [expr.const]/5? In your case, it does evaluate lvalue-to-rvalue conversion (5.8) and neither (5.8.1) nor (5.8.2) is satisfied.

That's, The lvalue-to-rvalue conversion is applied to the non-volatile glvalue rf, but the expression rf is neither usable in a constant expression (because it is not potentially-constant constant-initialized or constexpr) nor refers to an object whose lifetime began within the evaluation of expression rf (because the lifetime of the variable rf began before the evaluation of the expression rf). Hence, the expression rf is not a core constant expression and therefore not a constant expression (can't be used as an expression anywhere when a constant expression is required)

Also, note that both [expr.const]/(5.10) and [expr.const]/(5.12) have not been reached yet: (5.8) is tried first.

the error comes from

    constexpr int  v = rf;  // #1

you are trying to make a constexpr equal to something that is not. The constexpr is evaluated at compile time but rf is calculated only at run time. That means that the compiler will try to make v equal to something that was not calculated yet.

Related