This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Moved to DR at the February, 2014 meeting.]
Bullet 2 sub-bullet 2 of 9.4.4 [dcl.init.ref] paragraph 5 says,
Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (9.4 [dcl.init]). The reference is then bound to the temporary.
It is not clear what “using the rules for a non-reference copy-initialization” means. If it means that the temporary is initialized as if it were a standalone variable, the last bullet of 9.4 [dcl.init] paragraph 17 could apply:
Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 12.2.2.5 [over.match.copy], and the best one is chosen through overload resolution (12.2 [over.match]). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type. The temporary is a prvalue. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.
That is, for an example like
struct X { X(int) {} X(X const &) = delete; }; void f() { X const &x = 0; }
the specification requires creation of a temporary X(0), copying that tempoary to another temporary (subject to copy elision), and binding the reference to that second temporary. In the example above, because the copy constructor is deleted, the example is ill-formed, although current implementations fail to diagnose it as an error.
Is this intended?
Proposed resolution (September, 2013):
Change the last bullet of 9.4.4 [dcl.init.ref] paragraph 5, breaking it into sub-bullets, and the subsequent example as follows:
Otherwise:
If T1 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]); the program is ill-formed if the corresponding non-reference copy-initialization would be ill-formed. The result of the call to the conversion function, as described for the non-reference copy-initialization, is then used to direct-initialize the reference. The program is ill-formed if the direct-initialization does not result in a direct binding or if it involves a user-defined conversion.
If T1 is a non-class type, a temporary of type
“cv1 T1” is created
and copy-initialized (9.4 [dcl.init]) from the
initializer expression using the rules for a non-reference
copy-initialization (9.4 [dcl.init]). The reference is then
bound to the temporary.
If T1 is reference-related
to T2,:
cv1 shall be the same cv-qualification as, or greater
cv-qualification than, cv2.; and
If T1 is reference-related to T2 and
if the reference is an rvalue reference, the initializer
expression shall not be an lvalue.
[Example:
struct Banana { }; struct Enigma { operator const Banana(); }; void enigmatic() { typedef const Banana ConstBanana; Banana &&banana1 = ConstBanana(); // ill-formed Banana &&banana2 = Enigma(); // ill-formed } const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 ...
Change 12.2.2.5 [over.match.copy] paragraph 1 as follows:
Under the conditions specified in 9.4 [dcl.init], as part of a copy-initialization of an object of class type, a user-defined conversion can be invoked to convert an initializer expression to the type of the object being initialized. Overload resolution is used to select the user-defined conversion to be invoked. [Note: The conversion performed for indirect binding to a reference to a possibly cv-qualified class type is determined in terms of a corresponding non-reference copy-initialization. —end note] Assuming that