Title
Unclear rules for reference initialization with conversion
Status
tentatively ready
Section
9.4.4 [dcl.init.ref]
Submitter
Anoop Rana

Created on 2024-08-13.00:00:00 last changed 1 week ago

Messages

Date: 2025-02-15.00:00:00

Proposed resolution (February, 2025):

Change in 9.4.4 [dcl.init.ref] bullet 5.4.1 as follows:

If T1 or T2 is a class type, user-defined conversions are considered using the rules for copy-initialization of an object of type “cv1 T1” by user-defined conversion (9.4 [dcl.init], 12.2.2.5 [over.match.copy], 12.2.2.6 [over.match.conv]); the program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed. The result E of the call to the conversion function, as described for the non-reference copy-initialization, is then used to direct-initialize the reference using the form ( E ). For this direct-initialization, user-defined conversions are not considered.
Date: 2025-02-15.00:00:00

Additional notes (February, 2025)

Permitting a binding of X&& to a const Y seems ill-advised; the change effected by issue 1604 in that regard is intended.

In more detail, copy-initializing a T object from a cv T prvalue succeeds:

  struct X { X() = default; X(X&&) = delete; };
  using CX = const X;
  X x = CX();    // OK, default-initializes x

However, even with guaranteed copy elision, the pre-CWG1604 model does not handle derived classes appropriately when reference binding:

  struct X {
    X() = default;
    X(X&&) = delete;
  };
  struct Y : X {};
  struct Z {
    operator Y() { return Y(); }
  };
  X&& x = Z();

In this case, the rvalue reference x should bind directly to the Y materialized prvalue; there should never be an attempt to copy-initialize an X from Z to satisfy the reference binding. However, such direct reference binding would not be expected to work for a const Y prvalue.

Date: 2025-02-25.21:32:59

(From submission #596.)

It is unclear whether 9.4.4 [dcl.init.ref] bullet 5.4.1 intends list-initialization or not-list-initializaiton when it talks about direct-initialization.

Furthermore, the following example was well-formed before the resolution of issue 1604 was applied:

  struct X { };

  struct Y : X {};

  struct Z {
    operator const Y () const;
  };

  Z z;
  X&& r = z; // #1, ill-formed; was well-formed before CWG1604

Possible resolution (January, 2025) [SUPERSEDED]:

Change in 9.4.4 [dcl.init.ref] bullet 5.4.1 as follows:

If T1 or T2 is a class type, user-defined conversions are considered using the rules for copy-initialization of an object of type “cv1 T1” by user-defined conversion (9.4 [dcl.init], 12.2.2.5 [over.match.copy], 12.2.2.6 [over.match.conv]); the program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed. The result E of the call to the conversion function, as described for the non-reference copy-initialization, is then used to direct-initialize the reference using the form ( E ); if E is a prvalue, its cv-qualification is adjusted to cv1. For this direct-initialization, user-defined conversions are not considered.
History
Date User Action Args
2025-03-04 13:19:59adminsetmessages: + msg7976
2025-03-04 13:19:59adminsetstatus: open -> tentatively ready
2025-02-25 21:32:59adminsetmessages: + msg7968
2024-08-13 00:00:00admincreate