cplusplus / CWG

Core Working Group
24 stars 7 forks source link

[dcl.fct.def.coroutine] p13 A xvalue with its initial type "lvalue reference to cv T" #43

Open xmh0511 opened 2 years ago

xmh0511 commented 2 years ago

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

[dcl.fct.def.coroutine] p13 says

For a parameter of type cv T, the copy is a variable of type cv T with automatic storage duration that is direct-initialized from an xvalue of type T referring to the parameter.

How is such an xvalue produced if T is "lvalue reference to cv U"? Even though we didn't explicitly specify whether an expression of type "lvalue reference to object type" can be an xvalue or not, anyway, from the convention and all rules defined in [expr], there is no such an xvalue. Basically, almost all of the expressions with "lvalue reference to object type" are lvalues.

Suggested resolution:

For a parameter of type cv T, the copy is a variable of type cv T with automatic storage duration that is direct-initialized as defined in the following:

  • Assume that an id-expression P names the parameter:
    • If T is "reference to cv2 U", is direct-initialized from the xvalue static_cast<cv2 U&&>(P),
    • otherwise, is direct-initialized from the xvalue const_cast<T&&>(P)

This can make xvalue clear defined in this rule. Change [dcl.fct.def.coroutine.note] 2 to

An original parameter object ~is never~ cannot be a const or volatile object ([basic.type.qualifier]).

An object denoted by an xvalue of cv-unqualified that type remains no change if it is a const or volatile object. "is never" sounds like this property would be changed after an xvalue denoting the object. The intent is that the object denoted by the xvalue should be a non-const non-volatile object in order to make the program be well-formed if any modification will be done through the xvalue.

This issue is also mentioned in https://github.com/cplusplus/draft/issues/4870, but that issue did not clearly expound the thought.

jensmaurer commented 2 years ago

I agree the parameter copy doesn't work as intended for lvalue reference parameters. I disagree with your proposed resolution; I think we just want to carve out lvalue references and leave the rest alone. Note that those copies strip top-level cv-qualification from the declared types of the parameters.

The "is never" phrasing refers to the fact that the parameter object created in the caller is never a const or volatile object, so the cv-stripping doesn't result in undefined behavior.

xmh0511 commented 2 years ago

I disagree with your proposed resolution; I think we just want to carve out lvalue references and leave the rest alone. Note that those copies strip top-level cv-qualification from the declared types of the parameters.

The proposal trys to clarify how the xvalue sources from. For reference type, there is no top-level cv-qualification, static_cast<cv2 U&&>(P)(change cv to cv2, they are different cv-qualifications) is fine to denote the xvalue in the intent. For non-reference type, const_cast<T&&>(P) denotes the xvalue with discarding the top-level cv-qualification. Use cv was an omittion, the intent is that:

If T is "reference to cv2 U", is direct-initialized from the xvalue static_cast<cv2 U&&>(P),

frederick-vs-ja commented 1 year ago

I guess we can carve all reference types and avoid saying the exact form of initialization for references.

For a parameter of object type cv T, the copy is a variable of type cv T with automatic storage duration that is direct-initialized from an xvalue of type T referring to the parameter. For a parameter of reference type R, the copy is a variable of type R with automatic storage duration that binds to the same object or function as the parameter.

Or...

For a parameter of object type cv T [...]. For a parameter of reference type R whose name is denoted by r, the copy is a variable of type R with automatic storage duration that is direct-initialized from static_cast<R>(r).