Title
Copy-initialization of temporary in reference direct-initialization
Status
cd5
Section
9.4.4 [dcl.init.ref]
Submitter
Richard Smith

Created on 2016-05-25.00:00:00 last changed 7 months ago

Messages

Date: 2018-11-15.00:00:00

Proposed resolution (November, 2018):

  1. Change 9.4.5 [dcl.init.list] bullet 3.10 as follows:

  2. Otherwise, if T is a reference type, a prvalue of the type referenced by T is generated. The prvalue initializes its result object by copy-list-initialization or direct-list-initialization, depending on the kind of initialization for the reference. The prvalue is then used to direct-initialize the reference. [Note: As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. —end note]
  3. Add the following to the example in 9.4.5 [dcl.init.list] bullet 3.10:

  4.   struct A { } a;
      struct B { explicit B(const A&); };
      const B &b2(a);  // error: cannot copy-initialize B temporary from A
    
  5. Change 12.2.2.7 [over.match.ref] bullet 1.1 as follows:

  6. ...For direct-initialization, those explicit conversion functions that are not hidden within S and yield type “lvalue reference to cv2 T2(when initializing an lvalue reference or an rvalue reference to function) or “cv2 T2 or “rvalue reference to cv2 T2(when initializing an rvalue reference or an lvalue reference to function), respectively, where T2 is the same type as T or can be converted to type T with a qualification conversion (7.3.6 [conv.qual]), are also candidate functions.
Date: 2018-03-15.00:00:00

Notes from the March, 2018 meeting:

CWG felt that initialization of the temporary should always be copy initialization, regardless of whether the top-level initialization is copy or direct initialization. This would make #2, #3, #5, and #6 all ill-formed.

Date: 2019-02-15.00:00:00

[Accepted as a DR at the February, 2019 meeting.]

Consider the following example:

   struct A {} a; 
   struct B { explicit B(const A&); }; 

   struct D { D(); }; 
   struct C { explicit operator D(); } c; 

   B b1(a);            // #1, ok 
   const B &b2{a};     // #2. ok 
   const B &b3(a);     // #3, error 

   D d1(c);            // ok 
   const D &d2{c};     // ok 
   const D &d3(c);     // #6, ok 

The disparity between #3 and #6 is suprising, as is the difference from #1 and #2. The reason for this difference is in 9.4.5 [dcl.init.list] bullet 3.10:

Otherwise, if T is a reference type, a prvalue of the type referenced by T is generated. The prvalue initializes its result object by copy-list-initialization or direct-list-initialization, depending on the kind of initialization for the reference. The prvalue is then used to direct-initialize the reference.

(reflecting the resolution of issue 1494).

History
Date User Action Args
2020-12-15 00:00:00adminsetmessages: + msg6395
2020-12-15 00:00:00adminsetstatus: drafting -> cd5
2018-04-11 00:00:00adminsetmessages: + msg6196
2018-04-11 00:00:00adminsetstatus: open -> drafting
2016-05-25 00:00:00admincreate