Search code examples
c++language-lawyerrvalue-reference

In the C++ 20 specification, where is the rule saying an rvalue reference cannot bind to an lvalue?


Of course, this will not compile:

struct X {};
X&& x = X();
X&& x2 = x; // error: rvalue reference to type 'X' cannot bind to lvalue of type 'X'

Where is the relevant rule to this in the C++20 specification?

I read the section '9.4.3 References', but I cannot find the rule (I'm a novice on the C++ specification).

As a side note, I also cannot find the rule that permits the last line of the following (maybe finding it will help the main problem):

X x3;
X& x4 = x3;
X& x5 = x4;

Solution

  • As commented by François Andrieux and User17732522, the key point is interpreting the type of the initializer expression of a declaration.

    The rule (5) of 9.4.3 says:

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

    When interpreting 'an expression of type T2', the rule (1) of 7.2.2 is applied:

    If an expression initially has the type “reference to T” (9.3.3.2, 9.4.3), the type is adjusted to T prior to any further analysis. ...

    So, when applying the rule (5) of 9.4.3 to the X&& x2 = x;, T1 is X and T2 is also X. Because T1 and T2 are the same type, T1 is similar to T2 and T1 is reference-related to T2. This satisfies the condition of the rule (5.4.4) of 9.4.3, which says:

    ... - if the reference is an rvalue reference, the initializer expression shall not be an lvalue.

    Therefore, the syntax does not permit X&& x = X(); X&& x2 = x; because the initializer expression x is an lvalue.

    In the second example, the syntax permits X& x4 = x3; X& x5 = x4; by applying the rule (5.1) of 9.4.3.