[expr.prop] (original) (raw)

7.2.1 Value category [basic.lval]

Expressions are categorized according to the taxonomy in Figure 1.

categories expression expression glvalue glvalue expression->glvalue rvalue rvalue expression->rvalue lvalue lvalue glvalue->lvalue xvalue xvalue glvalue->xvalue rvalue->xvalue prvalue prvalue rvalue->prvalue

Figure 1: Expression category taxonomy [fig:basic.lval]

Every expression belongs to exactly one of the fundamental classifications in this taxonomy: lvalue, xvalue, or prvalue.

This property of an expression is called its value category.

[ Note

:

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

:

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 classify expressions, not values.

end note

]

[ Note

:

An expression is an xvalue if it is:

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

]

[ Example

:

struct A { int m; }; A&& operator+(A, A); A&& f();

A a; A&& ar = static_cast<A&&>(a);

The expressions f(), f().m, static_­cast<A&&>(a), and a + aare xvalues.

The expression ar is an lvalue.

end example

]

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 Vis sometimes said to have or name the value V.

The result object of a prvalue is the object initialized by the prvalue; a non-discarded prvalue that is used to compute the value of an operand of a built-in operator or a prvalue that has type cv voidhas no result object.

[ Note

:

Except when the prvalue is the operand of a decltype-specifier, a prvalue of class or array 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 expects a prvalue for that operand, thelvalue-to-rvalue, array-to-pointer, or function-to-pointer standard conversions are applied to convert the expression to a prvalue.

[ Note

:

An attempt to bind an rvalue reference to an lvalue is not such a context; see [dcl.init.ref].

end note

]

[ Note

:

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

:

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

]

Whenever a prvalue appears as an operand of an operator that expects a glvalue for that operand, thetemporary materialization conversion is applied to convert the expression to an xvalue.

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.

Unless otherwise indicated ([dcl.type.simple]), a prvalue shall always have complete type or the void type; if it has a class type or (possibly multi-dimensional) array of class type, that class shall not be an abstract class ([class.abstract]).

A glvalue shall not have type cv void.

[ Note

:

A glvalue may have complete or incomplete non-void type.

Class and array prvalues can have cv-qualified types; other prvalues always have cv-unqualified types.

See [expr.type].

end note

]

An lvalue is modifiable unless its type is const-qualified or is a function type.

If a program attempts to access ([defns.access]) the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:51

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.

[ Note

:

Unlike in C, C++ has no accesses of class type.

end note

]

7.2.2 Type [expr.type]

If an expression initially has the type “reference toT” ([dcl.ref], [dcl.init.ref]), the type is adjusted toT prior to any further analysis.

The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.

[ Note

:

Before the lifetime of the reference has started or after it has ended, the behavior is undefined (see [basic.life]).

end note

]

If a prvalue initially has the type “cv T”, whereT is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

The composite pointer type of two operands p1 andp2 having types T1 and T2, respectively, where at least one is a pointer or pointer-to-member type orstd​::​nullptr_­t, is:

[ Example

:

typedef void *p; typedef const int *q; typedef int **pi; typedef const int **pci;

The composite pointer type of p and q is “pointer to const void”; the composite pointer type of pi and pci is “pointer to const pointer toconst int”.

end example

]

7.2.3 Context dependence [expr.context]

An unevaluated operand is not evaluated.

[ Note

:

In an unevaluated operand, a non-static class member may be named ([expr.prim.id]) and naming of objects or functions does not, by itself, require that a definition be provided ([basic.def.odr]).

An unevaluated operand is considered a full-expression.

end note

]

In some contexts, an expression only appears for its side effects.

Such an expression is called a discarded-value expression.

The array-to-pointerand function-to-pointer standard conversions are not applied.

The lvalue-to-rvalue conversion is applied if and only if the expression is a glvalue of volatile-qualified type and it is one of the following:

[ Note

:

Using an overloaded operator causes a function call; the above covers only operators with built-in meaning.

end note

]

If the (possibly converted) expression is a prvalue, the temporary materialization conversion is applied.

[ Note

:

If the expression is an lvalue of class type, it must have a volatile copy constructor to initialize the temporary object that is the result object of the lvalue-to-rvalue conversion.

end note

]

The glvalue expression is evaluated and its value is discarded.