3
votes

Consider the following C++11 code:

int& f();

int&& i = f();

This produces an error:

cannot bind ‘int’ lvalue to ‘int&&’

I understand why, but I'm trying to justify it from the language in the standard.

Paraphrasing C++11 N3485 8.5.3.5:

A reference to int is initialized by an expression of type int as follows: (yes)

If the reference is an rvalue reference: (yes)

If the initializer expression: (yes)

  1. is an xvalue, class prvalue, array prvalue or function lvalue (no?), or
  2. has class type [snip] (no)

Is it the case that neither of these two points apply? So we should just assume it is ill-formed because neither do?

How can you determine from the standard that you can't initialize an rvalue reference to int with an lvalue of type int?

1
This is why std::move exists.chris
I haven't taken a close look at that part of the Standard, but wouldn't function lvalue be a variable that refers to a function (rather than call the function), i.e. f rather than f()?jogojapan
@chris: Sort of yes, std::move returns an rvalue reference, which when called as a postfix function call expression is an xvalue expression.Andrew Tomazos
@jogojapan: Yes, I think a function lvalue is an lvalue expression of function type - not a postfix function call expression.Andrew Tomazos
Well then, since the initializer expression isn't an xvalue, prvalue or function lvalue, the section you quoted doesn't apply, right? As far as I understand, the following section ("Otherwise....") would have to be applied, and in order to answer your question we have to work out why that can't be done. According to what it says there, it's related to the rules for "non-reference copy initialization".jogojapan

1 Answers

3
votes

I think you missed the last bullet of that article (8.5.3p5), that states:

If T1 is reference-related to T2 and the reference is an rvalue reference, the initializer expression shall not be an lvalue.