Skip to content

Instantly share code, notes, and snippets.

@thynson
Last active January 22, 2022 16:12
Show Gist options
  • Save thynson/b476ee2c647e706d1ecbc1686abd8e43 to your computer and use it in GitHub Desktop.
Save thynson/b476ee2c647e706d1ecbc1686abd8e43 to your computer and use it in GitHub Desktop.
C++ 17 Value Category System

C++ 17 Value Category System

-----------------------------
|   glvalue       |         |
-----------------------------
| lvalue | xvalue | prvalue |
-----------------------------
|        |     rvalue       |
-----------------------------

What is xvalue, by definition of lvalue and rvalue

extern T y();
T x = y(); 

x is lvalue and y() is rvalue. For the belowing code

T x = T(y()); 

x is still lvalue and expression y() is still rvalue but the intermediate expression T(...) is what? If we assign a name to it. The above code becomes

T z = y();
T x = std::move(z);

We can see:

  1. z appears at left side of assignment hence it's a lvalue

  2. std::move(z) appears at right hand side of assignment hence it's a rvalue.

Be minded that z std::move(z) are equivalence as the exprssion T(...) in privous code snip, and here T(...) has both property of rvalue, and property of lvalue except a name.

In C++17, such expression has a new category called xvalue. An xvalue is a glvalue as well as a rvalue at the same time. This result in:

  1. All xvalue must be optimized out, as they have no name and eventually they are only used to initialize a lvalue, this behavior is mandatory

  2. Due to all xvalue is optimzied out, C++ 17 is able to allow initialize a object of class T, which is non-copyable and non-movable, from xvalue of T, as all xvalue is optimized out, that object is actually constructed in the same way as the most right side prvalue or T.

struct X
{
   X(1);
   X(const X &) = delete;
   X(X&&) = delete;
};

X make_object()
{
   return X{1};
   //     ^ prvalue, not xvalue because glvalue is not here
}

int main()
{
    X x = make_object();
    //^ lvalue (and also glvalue)
    
    X y = X(make_object());
    //    ^ prvalue and implicitically converted to xvalue as it is expected by a glvalue (`y`)
    
    
    
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment