Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What standard clause mandates this lvalue-to-rvalue conversion?

Given:

int main() {
   int x = 0;
   int y = x; // <---
}

Could someone please tell me which clause of the standard (2003 preferred) mandates the conversion of the expression x from lvalue to rvalue in the initialisation of the object y?

(Or, if I'm mistaken and no such conversion takes place, then I'd like to learn that too!)

like image 379
Lightness Races in Orbit Avatar asked Jun 16 '11 18:06

Lightness Races in Orbit


3 Answers

I find it easier (if maybe not 100% precise) to think of lvalue-s as real objects and rvalue-s as the value stored in the object. The expression x is an lvalue expression that refers to the object x defined in the first line, but when used as the right hand side of an assignment to a type that is not a user defined type the actual value is read, and that is where the conversion from lvalue to rvalue is performed: reading the contents of the object.

As to the specific clause in the standard that dictates that conversion... well, the closest that I can think is 4.1 [conv.lvalue]/2 (Lvalue to Rvalue conversion):

The value contained in the object indicated by the lvalue is the rvalue result.

The requirement that the right hand side of the assignment is an rvalue is either implicit or missing from 5.17 [expr.ass], but that is the case or else the following expression would be an error since the rhs is an rvalue and there is no rvalue-to-lvalue conversion:

int x = 5;

EDIT: For initialization, 8.5 [dcl.init]/14, last bullet (which refers to fundamental types) states (emphasis mine):

  • Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. [...]

That value there means that the lvalue expression in your example is read (i.e. converted to an rvalue). At any rate the previous paragraph that referred to assignment could be applied here: if initialization required an lvalue rather than an rvalue, the expression int i = 0; would be ill-formed.

like image 158
David Rodríguez - dribeas Avatar answered Nov 06 '22 06:11

David Rodríguez - dribeas


I do believe that this is intuitive to some degree (what others already said - the value is needed, so there is an obvious need to convert the object designator to the value contained therein). The best I could come up with, by 4p3:

An expression e can be implicitly converted to a type T if and only if the declaration "T t=e;" is well-formed, for some invented temporary variable t (8.5). The effect of the implicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is a reference type (8.3.2), and an rvalue otherwise. The expression e is used as an lvalue if and only if the initialization uses it as an lvalue.

Note the "if and only if" at the end - the initializer therefor is used as an rvalue, because the initialization uses it as an rvalue (result of the conversion). So by 3.10p7

Whenever an lvalue appears in a context where an rvalue is expected, the lvalue is converted to an rvalue; see 4.1, 4.2, and 4.3.


EDIT: The paragraph for entering 4p3 can be found at 8.5p16, last bullet:

Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression.

Also note the comments below.

like image 8
Johannes Schaub - litb Avatar answered Nov 06 '22 06:11

Johannes Schaub - litb


Is this what you're looking for:

§3.10/7

Whenever an lvalue appears in a context where an rvalue is expected, the lvalue is converted to an rvalue; see 4.1, 4.2, and 4.3.

And I think when you write int y = x, it basically copies the value contained in the object x which is a lvalue, but the value itself is an rvalue, hence the context expects an rvalue.

§4.1/2 says,

The value contained in the object indicated by the lvalue is the rvalue result.

Maybe these two quotations clarify your doubt. Correct me if my understanding is wrong. I would like to learn new things.


@Tomalak's comment:

My problem with this is that int& y = x; is valid, so in this case of course x may not be an rvalue. I don't know how irrelevant the difference in my example makes that, though

Well int &y = x does NOT copy the value. It just creates an alias of the object itself. But as I previously said int y = x, basically copies the value which is an rvalue. Hence, the context expects an rvalue, as a copying is being done here.

like image 2
Nawaz Avatar answered Nov 06 '22 05:11

Nawaz