cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[expr.const] p8 What does an unspecified object intend to mean in constant context? #453

Closed xmh0511 closed 11 months ago

xmh0511 commented 11 months ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

[expr.const] p8 says:

For such a reference that is not usable in constant expressions, the reference is treated as binding to an unspecified object of the referenced type whose lifetime and that of all subobjects includes the entire constant evaluation and whose dynamic type is constexpr-unknown.

The relevant example is:

constexpr int foo(int& rf){
  constexpr int v = rf;  // #1
}

The relevant rules that determine whether the full-expression of the initialization of the variable v is [expr.const] p5.9

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

  • a non-volatile glvalue that refers to an object that is usable in constant expressions, or
  • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of E;

[expr.const] p8 says that rf binds to an unspecified object, however, what is the intent of saying unspecified object here? According to [intro.abstract] p3, unspecified behavior has multiple observable behaviors, by this logic, does it mean rf can refer to an object that is usable or not usable in constant expressions, which means, whether #1 is a constant expression or not is unspecified?

However, in most major implementations, this example is constantly ill-formed, and the older version standard(i.e. c++20) clearly says this example is ill-formed, the relevant rules in c++20 are removed and seem to be covered by [expr.const] p8, however the intent of the unspecified object is not clear in this case.

Suggested Resolution

Clarify what the unspecified object intends to mean in this case

frederick-vs-ja commented 11 months ago

It seems clear to me that an unspecified object is not considered usable in constant expressions.

The example shown below says (IIUC whether the outer function is constexpr doesn't matter):

void splash(Swim& swam) {
    // [...]
    static_assert(pswam->phelps() == 28);   // error: lvalue-to-rvalue conversion on a pointer
                                            // not usable in constant expressions
    // [...]
    static_assert(swam.coughlin == 12);     // error: lvalue-to-rvalue conversion on an object
                                            // not usable in constant expressions
}

Do you mean that these comments lack support from the normative wording?

xmh0511 commented 11 months ago

It seems clear to me that an unspecified object is not considered usable in constant expressions.

The example shown below says (IIUC whether the outer function is constexpr doesn't matter):

void splash(Swim& swam) {
    // [...]
    static_assert(pswam->phelps() == 28);   // error: lvalue-to-rvalue conversion on a pointer
                                            // not usable in constant expressions
    // [...]
    static_assert(swam.coughlin == 12);     // error: lvalue-to-rvalue conversion on an object
                                            // not usable in constant expressions
}

Do you mean that these comments lack support from the normative wording?

The issue is unspecified object does not mean it is not usable in constant expressions because it is unspecified.

frederick-vs-ja commented 11 months ago

It seems clear to me that an unspecified object is not considered usable in constant expressions. The example shown below says (IIUC whether the outer function is constexpr doesn't matter):

void splash(Swim& swam) {
    // [...]
    static_assert(pswam->phelps() == 28);   // error: lvalue-to-rvalue conversion on a pointer
                                            // not usable in constant expressions
    // [...]
    static_assert(swam.coughlin == 12);     // error: lvalue-to-rvalue conversion on an object
                                            // not usable in constant expressions
}

Do you mean that these comments lack support from the normative wording?

The issue is unspecified object does not mean it is not usable in constant expressions because it is unspecified.

I meant that the proposed resolution:

Clarify what the unspecified object intends to mean in this case

seems already done by the example.

Do you think it's currently unspecified whether static_assert(swam.coughlin == 12); is ill-formed because swam refers to an unspecified object (and thus the comment is not strictly correct)?

xmh0511 commented 11 months ago

seems already done by the example.

So, anyway, it lacks normative wording to clarify what the unspecified object intends to mean in constant expression evaluations, doesn't it?

Do you think it's currently unspecified whether static_assert(swam.coughlin == 12); is ill-formed because swam refers to an unspecified object (and thus the comment is not strictly correct)?

In terms of the status quo, it is. The unspecified behavior can have multiple reasonable observable behaviors, that is, it is not necessary to be the object that is not usable in constant expressions, it may or it may not, which in turn means, the example may be well-formed or ill-formed.

frederick-vs-ja commented 11 months ago

Clearer description and proposed resolution are already present in #340.

jensmaurer commented 11 months ago

Let's close this one, then.