7 Expressions [expr]

7.5 Primary expressions [expr.prim]

7.5.4 Names [expr.prim.id]

7.5.4.2 Unqualified names [expr.prim.id.unqual]

An identifier is only an id-expression if it has been suitably declared ([dcl.dcl]) or if it appears as part of a declarator-id ([dcl.decl]).
An identifier that names a coroutine parameter refers to the copy of the parameter ([dcl.fct.def.coroutine]).
[Note 1: 
A type-name or computed-type-specifier prefixed by ~ denotes the destructor of the type so named; see [expr.prim.id.dtor].
Within the definition of a non-static member function, an identifier that names a non-static member is transformed to a class member access expression ([class.mfct.non.static]).
— end note]
A component name of an unqualified-id U is
[Note 2: 
Other constructs that contain names to look up can have several component names ([expr.prim.id.qual], [dcl.type.simple], [dcl.type.elab], [dcl.mptr], [namespace.udecl], [temp.param], [temp.names], [temp.res]).
— end note]
The terminal name of a construct is the component name of that construct that appears lexically last.
The result is the entity denoted by the unqualified-id ([basic.lookup.unqual]).
If the unqualified-id appears in a lambda-expression at program point P and the entity is a local entity ([basic.pre]) or a variable declared by an init-capture ([expr.prim.lambda.capture]), then let S be the compound-statement of the innermost enclosing lambda-expression of P.
If naming the entity from outside of an unevaluated operand within S would refer to an entity captured by copy in some intervening lambda-expression, then let E be the innermost such lambda-expression.
  • If there is such a lambda-expression and if P is in E's function parameter scope but not its parameter-declaration-clause, then the type of the expression is the type of a class member access expression ([expr.ref]) naming the non-static data member that would be declared for such a capture in the object parameter ([dcl.fct]) of the function call operator of E.
    [Note 3: 
    If E is not declared mutable, the type of such an identifier will typically be const qualified.
    — end note]
  • Otherwise (if there is no such lambda-expression or if P either precedes E's function parameter scope or is in E's parameter-declaration-clause), the type of the expression is the type of the result.
[Note 4: 
If the entity is a template parameter object for a template parameter of type T ([temp.param]), the type of the expression is const T.
— end note]
[Note 5: 
The type will be adjusted as described in [expr.type] if it is cv-qualified or is a reference type.
— end note]
The expression is an xvalue if it is move-eligible (see below); an lvalue if the entity is a function, variable, structured binding, data member, or template parameter object; and a prvalue otherwise ([basic.lval]); it is a bit-field if the identifier designates a bit-field.
[Example 1: void f() { float x, &r = x; [=]() -> decltype((x)) { // lambda returns float const& because this lambda is not mutable and // x is an lvalue decltype(x) y1; // y1 has type float decltype((x)) y2 = y1; // y2 has type float const& decltype(r) r1 = y1; // r1 has type float& decltype((r)) r2 = y2; // r2 has type float const& return y2; }; [=](decltype((x)) y) { decltype((x)) z = x; // OK, y has type float&, z has type float const& }; [=] { [](decltype((x)) y) {}; // OK, lambda takes a parameter of type float const& [x=1](decltype((x)) y) { decltype((x)) z = x; // OK, y has type int&, z has type int const& }; }; } — end example]
An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type.
In the following contexts, an id-expression is move-eligible: