This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
[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):
Change 9.4.4 [dcl.init.ref] paragraph 5 as follows:
A reference to type βcv1 T1β is initialized by an expression of type βcv2 T2β as follows:
If the reference is an lvalue reference and the initializer expression
is an lvalue (but is not a bit-field), and βcv1 T1β is reference-compatible with βcv2 T2,β or
has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an lvalue of type βcv3 T3,β where βcv1 T1β is reference-compatible with βcv3 T3β (this conversion is selected by enumerating the applicable conversion functions (12.2.2.7 [over.match.ref]) and choosing the best one through overload resolution (12.2 [over.match])),
then the reference is bound
directlyto the initializer expression lvalue in the first case, and the reference is boundand to the lvalue result of the conversion in the second case.In these cases the reference is said to bind directly to the initializer expression.[Note: the usual lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions are not needed, and therefore are suppressed, when such direct bindings to lvalues are done. βend note][Example: ... βend example]
Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference and the initializer expression shall be an rvalue. [Example: ... βend example]
If the initializer expression is an rvalue, with T2 a class type, and βcv1 T1β is reference-compatible with βcv2 T2,β the reference is bound to the object represented by the rvalue (see 7.2.1 [basic.lval]) or to a sub-object within that object.
[Example: ... βend example]
If the initializer expression is an rvalue, with T2 an array type, and βcv1 T1β is reference-compatible with βcv2 T2,β the reference is bound to the object represented by the rvalue (see 7.2.1 [basic.lval]).
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. If T1 is reference-related to T2, cv1 must be the same cv-qualification as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed. [Example: ... βend example]
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.
Change 7.6.16 [expr.cond] bullet 3.1 as follows:
If E2 is an lvalue: E1 can be converted
to match E2 if E1 can be implicitly converted
(7.3 [conv]) to the type βlvalue reference to
T2β, subject to the constraint that in the conversion
the reference must bind directly (9.4.4 [dcl.init.ref]) to
E1 an lvalue.