Created on2012-02-06.00:00:00 last changed109 months ago
[Moved to DR at the November, 2014 meeting.]
Proposed resolution (February, 2014):
Change 9.5.4 [dcl.init.ref] paragraph 5 as follows:
A reference to type “cv1T1” is initializedby an expression of type “cv2T2” asfollows:
If the reference is an lvalue reference...
Otherwise, the reference shall be an lvalue reference to anon-volatile const type...
If the initializer expression
is an xvalue (but not a bit-field), class prvalue, array prvalueor function lvalue and “cv1T1” isreference-compatible with “cv2T2”, or
has a class type (i.e.,T2 is a class type),whereT1 is not reference-related toT2, and can beconverted to an xvalue, class prvalue, or function lvalue of type“cv3T3”, where“cv1T1” is reference-compatible with“cv3T3” (see12.2.2.7 [over.match.ref]),
then the reference is bound to the value of the initializer expressionin the first case and to the result of the conversion in the second case(or, in either case, to an appropriate base class subobject).
In thesecond case, if the reference is an rvalue reference and the secondstandard conversion sequence of the user-defined conversion sequenceincludes an lvalue-to-rvalue conversion, the program is ill-formed.[Example:struct A { }; struct B : A { } b; extern B f(); const A& rca2 = f(); // bound to theA subobject of theB rvalue. A&& rra = f(); // same as above struct X { operator B(); operator int&(); } x; const A& r = x; // bound to theA subobject of the result of the conversion int i2 = 42; int&& rri = static_cast<int&&>(i2); // bound directly toi2 B&& rrb = x; // bound directly to the result ofoperator Bint&& rri2 = X(); // error: lvalue-to-rvalue conversion applied to the // result ofoperator int&—end example]
Otherwise:
IfT1orT2 is a classtypeandT1 is not reference-related toT2,user-defined conversions are considered using the rules forcopy-initialization of an object of type “cv1T1” by user-defined conversion (9.5 [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-referencecopy-initialization would be ill-formed. The result of the call to theconversion function, as described for the non-referencecopy-initialization, is then used to direct-initialize the reference.
Theprogram is ill-formed if the direct-initialization does not result in adirect binding or if it involves a user-defined conversion.For this direct-initialization, user-defined conversions are notconsidered.
IfT1 is a non-class typeOtherwise,a temporary of type “cv1T1” is created andcopy-initialized (9.5 [dcl.init]) from the initializerexpression. The reference is then bound to the temporary.IfT1 is reference-related toT2:
cv1 shall be the same cv-qualification as, or greatercv-qualification than,cv2; and
if the reference is an rvalue reference, the initializer expressionshall not be an lvalue.
[Example:
struct Banana { }; struct Enigma { operator const Banana(); }; struct Alaska { operator Banana&(); }; void enigmatic() { typedef const Banana ConstBanana; Banana &&banana1 = ConstBanana(); // ill-formed Banana &&banana2 = Enigma(); // ill-formed Banana &&banana2 = Alaska(); // ill-formed } const double& rcd2 = 2; //rcd2 refers to temporary with value2.0 double&& rrd = 2; //rrd refers to temporary with value2.0 const volatile int cvi = 1; const int& r2 = cvi; // error: type qualifiers dropped struct A { operator volatile int&(); } a; const int& r3 = a; // error: type qualifiers dropped from result of conversion function double d2 = 1.0; double&& rrd2 = d2; // error:copyinginitializer is lvalue of related type struct X { operator int&(); }; int && rri2 = X(); // error: result of conversion function is lvalue of related type int i3 = 2; double&& rrd3 = i3; //rrd3 refers to temporary with value2.0—end example]
This resolution also resolvesissue 1572.
Notes from the April, 2013 meeting:
CWG felt that the declaration ofir2a should also be an error.
In the case of indirect reference binding, 9.5.4 [dcl.init.ref] paragraph 5only requires that the cv-qualification of the referred-totype be the same or greater than that of the initializer expressionwhen the types are reference-related. This leads to the followinganomaly:
class A { public: operator volatile int &(); }; A a; const int & ir1a = a.operator volatile int&(); // error! const int & ir2a = a; // allowed!ir = a.operator volatile int&();Is this intended?
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2017-02-06 00:00:00 | admin | set | status: drwp -> cd4 |
| 2015-05-25 00:00:00 | admin | set | status: dr -> drwp |
| 2015-04-13 00:00:00 | admin | set | messages: +msg5384 |
| 2014-11-24 00:00:00 | admin | set | status: ready -> dr |
| 2014-03-03 00:00:00 | admin | set | messages: +msg4834 |
| 2014-03-03 00:00:00 | admin | set | status: drafting -> ready |
| 2013-05-03 00:00:00 | admin | set | messages: +msg4336 |
| 2013-05-03 00:00:00 | admin | set | status: open -> drafting |
| 2012-02-06 00:00:00 | admin | create | |