3
votes

N4527 8.5.3 [dcl.init.ref]

5 A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

(5.1) — [...]

(5.1.1) — [...]

(5.1.2) — [...]

(5.2) — 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.

(5.2.1) — If the initializer expression

(5.2.1.1) — is an xvalue (but not a bit-field), class prvalue, array prvalue or function lvalue and “cv1 T1” is reference-compatible with “cv2 T2”, or

(5.2.1.2) — has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to an xvalue, class prvalue, or function lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3” (see 13.3.1.6),

then the reference is bound to the value of the initializer expression in the first case and to the result of the conversion in the second case (or, in either case, to an appropriate base class subobject).

(5.2.2) — Otherwise:

(5.2.2.1) — If T1 or T2 is a class type and T1 is not reference-related to T2, user-defined conversions are considered using the rules for copy-initialization of an object of type “cv1 T1” by userdefined conversion (8.5, 13.3.1.4, 13.3.1.5); 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. For this direct-initialization, user-defined conversions are not considered.

(5.2.2.2) — Otherwise, a temporary of type “cv1 T1” is created and copy-initialized (8.5) from the initializer expression. The reference is then bound to the temporary.

If T1 is reference-related to T2:

(5.2.2.3) — cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2 ; and

(5.2.2.4) — if the reference is an rvalue reference, the initializer expression shall not be an lvalue.

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.

What does the "last case" mean? 5.2.2(includes 5.2.2.1 and 5.2.2.2) or 5.2.2.2(just one)?

In other words, is 5.2.2.1 binding directly?

//case 5.2.1.2
struct X{};

struct Y{Y(X);};
const Y& y = X();   // bind directly

struct Z{operator X();};
const X& x = Z();   // bind directly

//case 5.2.2.1
struct A{operator int();};
const int& a = A(); // bind directly or not?

struct B{B(int);};
const B& b = 1;     // bind directly or not?
1
In the last two snippets in your example, either T1 or T2 is of class type. Therefore 5.2.2.2 doesn't apply (it does bind directly).0x499602D2

1 Answers

0
votes

The "last case" is referring to 5.2.2.2:

— Otherwise, a temporary of type “cv1 T1” is created and copy-initialized (8.5) from the initializer expression. The reference is then bound to the temporary.

This case is contingent on the previous condition being false, which is 5.2.2.1:

— If T1 or T2 is a class type and T1 is not reference-related to T2...

This isn't the case for the last two snippets of your example since in the first one A is of class type and int is not reference-related to A. In the second example, B is of class type and B is not reference-related to int. Since these are false 5.2.2.2 doesn't apply (they do bind directly).