This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


589. Direct binding of class and array rvalues in reference initialization

Section: 9.4.4  [dcl.init.ref]     Status: CD2     Submitter: Steve Adamczyk     Date: 26 July 2006

[Voted into WP at October, 2009 meeting.]

The resolutions of issues 391 and 450 say that the reference is “bound to” the class or array rvalue, but it does not say that the reference “binds directly” to the initializer, as it does for the cases that fall under the first bullet in 9.4.4 [dcl.init.ref] paragraph 5. However, this phrasing is important in determining the implicit conversion sequence for an argument passed to a parameter with reference type (12.2.4.2.5 [over.ics.ref]), where paragraph 2 says,

When a parameter of reference type is not bound directly to an argument expression, the conversion sequence is the one required to convert the argument expression to the underlying type of the reference according to 12.2.4.2 [over.best.ics]. Conceptually, this conversion sequence corresponds to copy-initializing a temporary of the underlying type with the argument expression.

The above-mentioned issue resolutions stated that no copy is to be made in such reference initializations, so the determination of the conversion sequence does not reflect the initialization semantics.

Simply using the “binds directly” terminology in the new wording may not be the right approach, however, as there are other places in the Standard that also give special treatment to directly-bound references. For example, the first bullet of 7.6.16 [expr.cond] paragraph 3 says,

If E2 is an lvalue: E1 can be converted to match E2 if E1 can be implicitly converted (7.3 [conv]) to the type “reference to T2,” subject to the constraint that in the conversion the reference must bind directly (9.4.4 [dcl.init.ref]) to E1.

The effect of simply saying that a reference “binds directly” to a class rvalue can be seen in this example:

    struct B { };
    struct D: B { };
    D f();
    void g(bool x, const B& br) {
        x ? f() : br;   // result would be lvalue
    }

It is not clear that treating this conditional expression as an lvalue is a desirable outcome, even if the result of f() were to “bind directly” to the const B& reference.

Proposed resolution (June, 2009):

  1. Change 9.4.4 [dcl.init.ref] paragraph 5 as follows:

  2. A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

    In all cases except the last (i.e., creating and initializing a temporary from the initializer expression), the reference is said to bind directly to the initializer expression.

  3. Change 7.6.16 [expr.cond] bullet 3.1 as follows: