Question

According to this document:

http://www.stroustrup.com/terminology.pdf

  1. l-values have identity and are not movable.
  2. pr-values are movable but don't have identity.
  3. x-values have identity and are movable.

I have a couple of questions around these.

a. What's the example of an x-value having identity? The following isn't legal:

Foo f;
&std::move(f);

b. I could overload the &-operator of class Foo and make it return this so that the following becomes legal:

&Foo(5);

But pr-values like Foo(5) cannot have identity. Or is there a subtler interpretation of identity?

Was it helpful?

Solution 2

Or is there a subtler interpretation of identity?

The document you linked contains these two definitions:

  • “has identity” – i.e. and address, a pointer, the user can determine whether two copies are identical, etc.
  • “can be moved from” – i.e. we are allowed to leave to source of a “copy” in some indeterminate, but valid state

Taking a look at the Standard we can gather the definition of an object (as per §1.8/1) is:

An object is a region of storage.

that as per, §1.7/1:

Every byte has a unique address.

has an address. This means that the definition is awfully broad and includes pretty much every object of any type of value (rvalue, xvalue, prvalue, lvalue, etc..).


What's the example of an x-value having identity?

The standard itself gives a list of expressions that generates xvalues (at §5/7):

An expression is an xvalue if it is:

  • the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type,
  • a cast to an rvalue reference to object type,
  • a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue, or
  • a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member.

In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether namedornot.

And as a follow up few examples are given. Here's an extension to them:

struct A { int m; };

A&& operator+(A, A);
A a;
A b;
a + b;   // xvalue

A&& f();
f();     // xvalue
f().m;   // xvalue

A a;
static_cast<A&&>(a);  // xvalue
std::move(a);         // xvalue

OTHER TIPS

The following from Stroutrup's The C++ Programming Language might clear this question up:

void f(vector<string>& vs)
{
vector<string>& v2 = std::move(vs);// move vs to v2
// ...
}

Here, std::move(vs) is an xvalue: it
clearly has identity (we can refer to
it as vs), but we have explicitly given
permission for it to be moved from by
calling std::move() (§3.3.2, §35.5.1).
For practical programming, thinking in
terms of rvalue and lvalue is usually 
sufficient. 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top