[expr.prim.id.unqual]

# 7 Expressions [[expr]](./#expr)

## 7.5 Primary expressions [[expr.prim]](expr.prim#id.unqual)

### 7.5.5 Names [[expr.prim.id]](expr.prim.id#unqual)

#### 7.5.5.2 Unqualified names [expr.prim.id.unqual]

[unqualified-id:](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")  
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")  
[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")  
[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]")  
[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]")  
~ [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
~ [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")  
[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1521)

An [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is only
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") if it has
been suitably declared ([[dcl]](dcl "9 Declarations"))
or if it appears as part of a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#1.sentence-1)

[*Note [1](#note-1)*:

For [*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")*s*, see [[over.oper]](over.oper "12.4 Overloaded operators"); for[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]")*s*, see [[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions"); for[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]")*s*, see [[over.literal]](over.literal "12.6 User-defined literals"); for[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s*, see [[temp.names]](temp.names "13.3 Names of template specializations")[.](#1.sentence-2)

A [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") prefixed by ~ denotes the destructor of the type so named;
see [[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5 Destruction")[.](#1.sentence-3)

â *end note*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1537)

A [*component name*](#def:component_name "7.5.5.2 Unqualified names [expr.prim.id.unqual]") of an [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") U is

- [(2.1)](#2.1)

U if it is a name or

- [(2.2)](#2.2)

the component name of
the [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") or [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") of U, if any[.](#2.sentence-1)

[*Note [2](#note-2)*:

Other constructs that contain names to look up can have several
component names ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"), [[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple type specifiers"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"), [[dcl.mptr]](dcl.mptr "9.3.4.4 Pointers to members"), [[namespace.udecl]](namespace.udecl "9.10 The using declaration"), [[temp.param]](temp.param "13.2 Template parameters"), [[temp.names]](temp.names "13.3 Names of template specializations"), [[temp.res]](temp.res "13.8 Name resolution"))[.](#2.sentence-2)

â *end note*]

The [*terminal name*](#def:name,terminal "7.5.5.2 Unqualified names [expr.prim.id.unqual]") of a construct is
the component name of that construct that appears lexically last[.](#2.sentence-3)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1554)

The result is the entity denoted by
the [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3 Unqualified name lookup"))[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1558)

If

- [(4.1)](#4.1)

the [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") appears in a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") at program point P,

- [(4.2)](#4.2)

the entity is a local entity ([[basic.pre]](basic.pre "6.1 Preamble"))
or a variable declared by an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures")),

- [(4.3)](#4.3)

naming the entity within the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of
the innermost enclosing [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") of P,
but not in an unevaluated operand, would refer to an entity captured by copy
in some intervening [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"), and

- [(4.4)](#4.4)

P is in the function parameter scope,
but not the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),
of the innermost such [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") E,

then
the type of the expression is
the type of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))
naming the non-static data member
that would be declared for such a capture
in the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the function call operator of E[.](#4.sentence-1)

[*Note [3](#note-3)*:

If E is not declared mutable,
the type of such an identifier will typically be const qualified[.](#4.sentence-2)

â *end note*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1589)

Otherwise,
if the [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") names a coroutine parameter,
the type of the expression is
that of the copy of the parameter ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")),
and the result is that copy[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1597)

Otherwise,
if the [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") names a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))
attached to a function *f* with return type U,

- [(6.1)](#6.1)

if U is âreference to Tâ,
then the type of the expression isconst T;

- [(6.2)](#6.2)

otherwise,
the type of the expression is const U[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1613)

Otherwise,
if the [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") appears in the predicate of a contract assertion C ([[basic.contract]](basic.contract "6.11 Contract assertions"))
and the entity is

- [(7.1)](#7.1)

a variable
declared outside of C of object type T,

- [(7.2)](#7.2)

a variable or template parameter
declared outside of C of type âreference to Tâ, or

- [(7.3)](#7.3)

a structured binding
of type T whose corresponding variable
is declared outside of C,

then the type of the expression is const T[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1635)

[*Example [1](#example-1)*: int n = 0;struct X { bool m(); };

struct Y {int z = 0; void f(int i, int* p, int& r, X x, X* px) pre (++n) // error: attempting to modify const lvalue pre (++i) // error: attempting to modify const lvalue pre (++(*p)) // OK pre (++r) // error: attempting to modify const lvalue pre (x.m()) // error: calling non-const member function pre (px->m()) // OK pre ([=,&i,*this] mutable {++n; // error: attempting to modify const lvalue++i; // error: attempting to modify const lvalue++p; // OK, refers to member of closure type++r; // OK, refers to non-reference member of closure type++this->z; // OK, captured *this++z; // OK, captured *thisint j = 17; [&]{int k = 34; ++i; // error: attempting to modify const lvalue++j; // OK++k; // OK}(); return true; }()); template <int N, int& R, int* P>void g() pre(++N) // error: attempting to modify prvalue pre(++R) // error: attempting to modify const lvalue pre(++(*P)); // OKint h() post(r : ++r) // error: attempting to modify const lvalue post(r: [=] mutable {++r; // OK, refers to member of closure typereturn true; }()); int& k() post(r : ++r); // error: attempting to modify const lvalue}; â *end example*]

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1687)

Otherwise, if the entity is a template parameter object for
a template parameter of type T ([[temp.param]](temp.param "13.2 Template parameters")),
the type of the expression is const T[.](#9.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1692)

In all other cases, the type of the expression is the type of the entity[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1695)

[*Note [4](#note-4)*:

The type will be adjusted as described in [[expr.type]](expr.type "7.2.2 Type") if it is cv-qualified or is a reference type[.](#11.sentence-1)

â *end note*]

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1701)

The expression is an xvalue if it is move-eligible (see below);
an lvalue
if the entity is a
function,
variable,
structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")),
result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")),
data member, or
template parameter object;
and a prvalue otherwise ([[basic.lval]](basic.lval "7.2.1 Value category"));
it is a bit-field if the identifier designates a bit-field[.](#12.sentence-1)

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1714)

If an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") E appears in the predicate of
a function contract assertion attached to a function *f* and denotes
a function parameter of *f* and the implementation introduces any temporary objects
to hold the value of that parameter as specified in [[class.temporary]](class.temporary "6.8.7 Temporary objects"),

- [(13.1)](#13.1)

if the contract assertion
is a precondition assertion
and the evaluation of the precondition assertion
is sequenced before the initialization of the parameter object,E refers to the most recently initialized such temporary object, and

- [(13.2)](#13.2)

if the contract assertion
is a postcondition assertion,
it is unspecified whether E refers to
one of the temporary objects or the parameter object;
the choice is consistent within a single evaluation of a postcondition assertion[.](#13.sentence-1)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1737)

If an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") E names a result binding
in a postcondition assertion
and the implementation introduces any temporary objects
to hold the result object as specified in [[class.temporary]](class.temporary "6.8.7 Temporary objects"),
and the postcondition assertion
is sequenced before the initialization of the result object ([[expr.call]](expr.call "7.6.1.3 Function call")),E refers to the most recently initialized such temporary object[.](#14.sentence-1)

[*Example [2](#example-2)*: void f() {float x, &r = x; [=]() -> decltype((x)) { // lambda returns float const& because this lambda is not mutable and// x is an lvaluedecltype(x) y1; // y1 has type floatdecltype((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*]

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1777)

An [*implicitly movable entity*](#def:entity,implicitly_movable "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is
a variable with automatic storage duration
that is either a non-volatile object or
an rvalue reference to a non-volatile object type[.](#15.sentence-1)

An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") ([[expr.prim.splice]](expr.prim.splice "7.5.9 Expression splicing"))
is [*move-eligible*](#def:move-eligible "7.5.5.2 Unqualified names [expr.prim.id.unqual]") if

- [(15.1)](#15.1)

it designates an implicitly movable entity,

- [(15.2)](#15.2)

it is the (possibly parenthesized)
operand of a return ([[stmt.return]](stmt.return "8.8.4 The return statement")) orco_return ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5 The co_­return statement")) statement or
of a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]") ([[expr.throw]](expr.throw "7.6.18 Throwing an exception")), and

- [(15.3)](#15.3)

each intervening scope between
the declaration of the entity and
the innermost enclosing scope of the expression
is a block scope and,
for a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]"),
is not the block scope of
a [*try-block*](except.pre#nt:try-block "14.1 Preamble [except.pre]") or [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]")[.](#15.sentence-2)
