[basic.lval]
7 Expressions [expr]
7.2 Properties of expressions [expr.prop]
7.2.1 Value category [basic.lval]
Figure 2 — Expression category taxonomy [fig:basic.lval]
Every expression belongs to exactly one of the fundamental categories in this taxonomy: lvalue, xvalue, or prvalue.
This property of an expression is called its value category.
[Note 1:
The discussion of each built-in operator in [expr.compound] indicates the category of the value it yields and the value categories of the operands it expects.
For example, the built-in assignment operators expect that the left operand is an lvalue and that the right operand is a prvalue and yield an lvalue as the result.
User-defined operators are functions, and the categories of values they expect and yield are determined by their parameter and return types.
— end note]
[Note 2:
Historically, lvalues and rvalues were so-called because they could appear on the left- and right-hand side of an assignment (although this is no longer generally true); glvalues are “generalized” lvalues, prvalues are “pure” rvalues, and xvalues are “eXpiring” lvalues.
Despite their names, these terms apply to expressions, not values.
— end note]
[Note 3:
An expression is an xvalue if it is:
- a move-eligible id-expression ([expr.prim.id.unqual]) or splice-expression ([expr.prim.splice]),
- the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type ([expr.call]),
- a cast to an rvalue reference to object type ([expr.type.conv], [expr.dynamic.cast], [expr.static.cast], [expr.reinterpret.cast], [expr.const.cast], [expr.cast]),
- a subscripting operation with an xvalue array operand ([expr.sub]),
- a class member access expression designating a non-static data member of non-reference type in which the object expression is an xvalue ([expr.ref]), or
- a .* pointer-to-member expression in which the first operand is an xvalue and the second operand is a pointer to data member ([expr.mptr.oper]).
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 named or not.
— end note]
The result of a glvalue is the entity denoted by the expression.
The result of a prvalue is the value that the expression stores into its context; a prvalue that has type cv void has no result.
A prvalue whose result is the value V is sometimes said to have or name the value V.
The result object of a prvalue is the object initialized by the prvalue; a prvalue that has type cv void has no result object.
[Note 4:
Except when the prvalue is the operand of a decltype-specifier, a prvalue of object type always has a result object.
For a discarded prvalue that has type other than cv void, a temporary object is materialized; see [expr.context].
— end note]
Whenever a glvalue appears as an operand of an operator that requires a prvalue for that operand, the lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), or function-to-pointer ([conv.func]) standard conversions are applied to convert the expression to a prvalue.
[Note 5:
An attempt to bind an rvalue reference to an lvalue is not such a context; see [dcl.init.ref].
— end note]
[Note 6:
Because cv-qualifiers are removed from the type of an expression of non-class type when the expression is converted to a prvalue, an lvalue of type const int can, for example, be used where a prvalue of type int is required.
— end note]
[Note 7:
There are no prvalue bit-fields; if a bit-field is converted to a prvalue ([conv.lval]), a prvalue of the type of the bit-field is created, which might then be promoted ([conv.prom]).
— end note]
[Note 8:
The discussion of reference initialization in [dcl.init.ref] and of temporaries in [class.temporary] indicates the behavior of lvalues and rvalues in other significant contexts.
— end note]
Unless otherwise indicated ([dcl.type.decltype]), a prvalue shall always have complete type or the void type; if it has a class type or (possibly multidimensional) array of class type, that class shall not be an abstract class ([class.abstract]).
A glvalue shall not have type cv void.
An lvalue is modifiable unless its type is const-qualified or is a function type.
An object of dynamic type is type-accessible through a glvalue of type if is similar ([conv.qual]) to:
- ,
- a type that is the signed or unsigned type corresponding to , or
- a char, unsigned char, or std::byte type.
If a program attempts to access ([defns.access]) the stored value of an object through a glvalue through which it is not type-accessible, the behavior is undefined.38
If a program invokes a defaulted copy/move constructor or copy/move assignment operator for a union of type U with a glvalue argument that does not denote an object of type cv U within its lifetime, the behavior is undefined.