10

I read this answer the part that caught my attention was this:

int i;
int* p = &i;
int& f();
int&& g();

int h();

h() // prvalue
g() // glvalue (xvalue)
f() // glvalue (lvalue)
i   // glvalue (lvalue)
*p  // glvalue (lvalue)

std::move(i)  // glvalue (xvalue)

and with this chart in mind

Expression type chart

I got confused.

If a glvalue is either an lvalue or an xvalue and an rvalue is either a prvalue or an xvalue, isn't it wrong to say that g() is a glvalue without saying that it is also an rvalue? The same with std::move(i).

What my version of the above code would look like:

h() // rvalue (prvalue)
g() // glvalue and rvalue (xvalue)
f() // glvalue (lvalue)
i   // glvalue (lvalue)
*p  // glvalue (lvalue)

std::move(i)  // glvalue and rvalue(xvalue)

As for what the standard says(I only quote the most related parts):

An rvalue (so-called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue

and

A glvalue (“generalized” lvalue) is an lvalue or an xvalue.

Of course, I could be wrong. If so, please help me out a little :)

  • 2
    Your selective quoting is severely misleading. "An rvalue [...] is an xvalue" is cut from a sentence which is structured "An rvalue [...] is an xvalue, temporary object [...] or a value [...]". Truncating the "or" parts significantly changes the meaning. – CB Bailey Jun 30 '17 at 15:15
  • @CharlesBailey well I did it on purpose because I guess that the most relevant part of that is the fact that rvalues are considered as xvalues. –  Jun 30 '17 at 15:23

2 Answers2

6

If a glvalue is either an lvalue or an xvalue and an rvalue is either a prvalue or an xvalue, isn't it wrong to say that g() is a glvalue without saying that it is also an rvalue?

Yes.

If g() is an xvalue, then it is both a glvalue and an rvalue.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    However it's not wrong to say "this overload set distinguishes between glvalues (where it does x) and prvalues (where it does y)" and "that overload set distinguishes between lvalues (where it does w) and rvalues (where it does z)". I can't off-hand think of situations where it is important to treat lvalues, xvalues and prvalues each differently, but such a trichotomy is possible – Caleth Jun 30 '17 at 15:57
  • 1
    @Caleth How exactly do you plan to distinguish prvalues and xvalues using overload resolution? – Columbo Jun 30 '17 at 16:17
  • @Columbo binding to `std::remove_const_t &`? ... are you saying that an `is_prvalue` trait is impossible? – Caleth Jun 30 '17 at 16:28
  • 1
    @Caleth What I'm saying is that overload resolution cannot (in general) distinguish between xvalues and prvalues. – Columbo Jun 30 '17 at 16:29
  • Thanks for the answer. But since my assumption was true and since every value is one of the following: lvalue, xvalue or prvalue, why are there even the categories glvalue and rvalue? –  Jun 30 '17 at 16:57
  • @NeiLee: So that the standard can make rules applying to glvalues and rvalues without having to list out all the options every time. It's called abstraction. It's also self-documenting (sort of) and gives us a tidy path from C's "lvalue" and "not lvalue" definitions. – Lightness Races in Orbit Jun 30 '17 at 17:01
  • @LightnessRacesinOrbit I think some it is due to convention. Like conventional current flows from positive to negative. Or "it puts the lotion on its skin..." – wally Jun 30 '17 at 19:13
3

As I understand it from here

  • glvalue == has identity and
  • rvalue == can be moved from.

So your analysis is correct because an xvalue

  • can be moved from and
  • has identity.
wally
  • 10,717
  • 5
  • 39
  • 72