5

I have been carefully studying rvalues and rvalue references, in detail, for a number of weeks. I have growing confidence that I have some clarity in understanding the difference between:

  • The type with which a variable or function parameter is defined (i.e. int x; vs. int && x = …;
  • The expression category of expressions, including those that may use a previously defined parameter (i.e., given the function definition A&& foo(), and given an expression consisting solely of foo(), the expression category is "xvalue")
  • The type of the result of evaluation of a subexpression when that expression is used within a containing expression (i.e., given the same definition of foo, the type of a subexpression foo() when used within a containing expression is A (not A&&)).

My question regards the difference between xvalue expressions and prvalue expressions (both of these expression categories being rvalues).

Given:

class A
{};

A&& foo() {…}
A goo() {…}

void test(A&& a) {…}

int main()
{
    test(foo()); // test() called with xvalue expression
    test(goo()); // test() called with prvalue expression
}

Note that the function test() is successfully called with both an xvalue expression, and a prvalue expression. (Please correct me if I have a misunderstanding about this.)

My question is: Since the function parameter A&& a to test successfully binds to both xvalues and to prvalues, what is the practical difference between xvalues and prvalues in terms of overload resolution?

Is there an example of a scenario in which the xvalue/prvalue nature of an expression results in different function overload resolution? Or is the distinction between xvalues and rvalues relevant only for other aspects of the language, independent of function overload resolution (for example, the result of decltype (i.e., see What is decltype(0 + 0)?))?

Enlico
  • 23,259
  • 6
  • 48
  • 102
Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181

1 Answers1

3

I don't believe there would be any difference in overload resolution, no.

There are plenty of other reasons to clarify what expressions are xvalues and prvalues, though. Xvalues are modifiable; prvalues are not. Xvalues are subject to the rules against improper uses of glvalues before or after the object's lifetime; this is never an issue with prvalues.

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • Note that `goo() = A();` builds and runs successfully in Visual Studio 2012 (which supposedly implements all C++11 features related to rvalue references) - since the left-hand side of this is a prvalue expression (if I'm correct about that), this *seems* to be an example where a prvalue is considered to be modifiable? – Dan Nissenbaum Dec 22 '12 at 05:09
  • For back-compatibility with C++03, a class's default assignment operators allow the left side to be an lvalue or rvalue. You can make a class act more like fundamental types by defining instead: `A& operator=(const A&) &;` – aschepler Dec 22 '12 at 12:51
  • The line of code `A& operator=(const A&) &;` does not compile in Visual Studio 2012 (when included within the class definition of `A`). I'm not familiar with the syntax of the `&` sign after a member function declaration - can you point the way? – Dan Nissenbaum Dec 22 '12 at 15:44
  • 2
    @Dan : That syntax is not supported in VC++ (even 2012); it's generally referred to as "move semantics for *this", and is described in [N2439](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm). – ildjarn Jan 04 '13 at 00:28