Files
2025-10-25 03:02:53 +03:00

2216 lines
139 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[expr.prim]
# 7 Expressions [[expr]](./#expr)
## 7.5 Primary expressions [expr.prim]
### [7.5.1](#grammar) Grammar [[expr.prim.grammar]](expr.prim.grammar)
[primary-expression:](#nt:primary-expression "7.5.1Grammar[expr.prim.grammar]")
[*literal*](lex.literal.kinds#nt:literal "5.13.1Kinds of literals[lex.literal.kinds]")
this
( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
[*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]")
[*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")
[*fold-expression*](#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]")
[*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]")
[*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")
### [7.5.2](#literal) Literals [[expr.prim.literal]](expr.prim.literal)
[1](#literal-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1249)
The type of a [*literal*](lex.literal.kinds#nt:literal "5.13.1Kinds of literals[lex.literal.kinds]") is determined based on its form as specified in [[lex.literal]](lex.literal "5.13Literals")[.](#literal-1.sentence-1)
A [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") is an lvalue
designating a corresponding string literal object ([[lex.string]](lex.string "5.13.5String literals")),
a [*user-defined-literal*](lex.ext#nt:user-defined-literal "5.13.9User-defined literals[lex.ext]") has the same value category
as the corresponding operator call expression described in [[lex.ext]](lex.ext "5.13.9User-defined literals"),
and any other [*literal*](lex.literal.kinds#nt:literal "5.13.1Kinds of literals[lex.literal.kinds]") is a prvalue[.](#literal-1.sentence-2)
### [7.5.3](#this) This [[expr.prim.this]](expr.prim.this)
[1](#this-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1263)
The keyword this names a pointer to the object for which an implicit object member
function ([[class.mfct.non.static]](class.mfct.non.static "11.4.3Non-static member functions")) is invoked or a non-static data member's
initializer ([[class.mem]](class.mem "11.4Class members")) is evaluated[.](#this-1.sentence-1)
[2](#this-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1269)
The [*current class*](#def:class,current "7.5.3This[expr.prim.this]") at a program point is
the class associated with the innermost class scope containing that point[.](#this-2.sentence-1)
[*Note [1](#this-note-1)*:
A [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") does not introduce a class scope[.](#this-2.sentence-2)
— *end note*]
[3](#this-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1276)
If the expression this appears within the predicate of a contract assertion ([[basic.contract.general]](basic.contract.general "6.11.1General"))
(including as the result of an implicit transformation ([[expr.prim.id.general]](#id.general "7.5.5.1General"))
and including in the bodies of nested [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s*)
and the current class
encloses the contract assertion,const is combined with the [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") used to generate the resulting type (see below)[.](#this-3.sentence-1)
[4](#this-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1286)
If a declaration declares a member function or member function template of a
class X, the expression this is a prvalue of type “pointer to[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") X”
wherever X is the current class
between the optional[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") and the end of the [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]"),[*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]"), or [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")[.](#this-4.sentence-1)
It shall not appear within
the declaration of
a static or explicit object member function
of the current class (although its type and value category
are defined within such member functions as they are within an implicit object
member function)[.](#this-4.sentence-2)
[*Note [2](#this-note-2)*:
This is because declaration matching does not
occur until the complete declarator is known[.](#this-4.sentence-3)
— *end note*]
[*Note [3](#this-note-3)*:
In a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]"),
the class being defined is not required to be complete
for purposes of [class member access](expr.ref "7.6.1.5Class member access[expr.ref]")[.](#this-4.sentence-4)
Class members declared later are not visible[.](#this-4.sentence-5)
[*Example [1](#this-example-1)*: struct A {char g(); template<class T> auto f(T t) -> decltype(t + g()){ return t + g(); }};template auto A::f(int t) -> decltype(t + g()); — *end example*]
— *end note*]
[5](#this-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1320)
Otherwise, if a [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]") declares a non-static data
member ([[class.mem]](class.mem "11.4Class members")) of a class X, the expression this is
a prvalue of type “pointer to X”
wherever X is the current class
within the
optional default member initializer ([[class.mem]](class.mem "11.4Class members"))[.](#this-5.sentence-1)
[6](#this-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1328)
The expression this shall not appear in any other context[.](#this-6.sentence-1)
[*Example [2](#this-example-2)*: class Outer {int a[sizeof(*this)]; // error: not inside a member functionunsigned int sz = sizeof(*this); // OK, in default member initializervoid f() {int b[sizeof(*this)]; // OKstruct Inner {int c[sizeof(*this)]; // error: not inside a member function of Inner}; }}; — *end example*]
### [7.5.4](#paren) Parentheses [[expr.prim.paren]](expr.prim.paren)
[1](#paren-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1349)
A parenthesized expression (E) is a primary expression whose type, result, and value category are identical to those of E[.](#paren-1.sentence-1)
The parenthesized expression can be used in exactly the same contexts as
those where E can be used, and with the same
meaning, except as otherwise indicated[.](#paren-1.sentence-2)
### [7.5.5](#id) Names [[expr.prim.id]](expr.prim.id)
#### [7.5.5.1](#id.general) General [[expr.prim.id.general]](expr.prim.id.general)
[id-expression:](#nt:id-expression "7.5.5.1General[expr.prim.id.general]")
[*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")
[*qualified-id*](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]")
[*pack-index-expression*](#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]")
[1](#id.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1368)
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a restricted form of a[*primary-expression*](#nt:primary-expression "7.5.1Grammar[expr.prim.grammar]")[.](#id.general-1.sentence-1)
[*Note [1](#id.general-note-1)*:
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") can appear after[. and -> operators](expr.ref "7.6.1.5Class member access[expr.ref]")[.](#id.general-1.sentence-2)
— *end note*]
[2](#id.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1378)
If an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") E denotes
a non-static non-type member of some class C at a point where
the current class ([[expr.prim.this]](#this "7.5.3This")) is X and
- [(2.1)](#id.general-2.1)
E is potentially evaluated orC is X or a base class of X, and
- [(2.2)](#id.general-2.2)
E is not the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") of
a class member access expression ([[expr.ref]](expr.ref "7.6.1.5Class member access")), and
- [(2.3)](#id.general-2.3)
E is not the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") of
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The reflection operator")), and
- [(2.4)](#id.general-2.4)
if E is a [*qualified-id*](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]"),E is not the un-parenthesized operand of
the unary & operator ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")),
the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is transformed into
a class member access expression using (*this) as the object expression[.](#id.general-2.sentence-1)
If this transformation occurs
in the predicate of a precondition assertion of a constructor of X or a postcondition assertion of a destructor of X,
the expression is ill-formed[.](#id.general-2.sentence-2)
[*Note [2](#id.general-note-2)*:
If C is not X or a base class of X,
the class member access expression is ill-formed[.](#id.general-2.sentence-3)
Also, if the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") occurs within
a static or explicit object member function,
the class member access is ill-formed[.](#id.general-2.sentence-4)
— *end note*]
This transformation does not apply in
the template definition context ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types"))[.](#id.general-2.sentence-5)
[*Example [1](#id.general-example-1)*: struct C {bool b;
C() pre(b) // error pre(&this->b) // OK pre(sizeof(b) > 0); // OK, b is not potentially evaluated.}; — *end example*]
[3](#id.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1423)
If an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") E denotes
a member M of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")) U:
- [(3.1)](#id.general-3.1)
If U is a non-static data member,E refers to M as a member of the lookup context of the terminal name of E (after any implicit transformation to
a class member access expression)[.](#id.general-3.1.sentence-1)
[*Example [2](#id.general-example-2)*:
o.x is interpreted as o.u.x,
where u names the anonymous union member[.](#id.general-3.1.sentence-2)
— *end example*]
- [(3.2)](#id.general-3.2)
Otherwise, E is interpreted as a class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access"))
that designates the member subobject M of
the anonymous union variable for U[.](#id.general-3.2.sentence-1)
[*Note [3](#id.general-note-3)*:
Under this interpretation, E no longer denotes a non-static data member[.](#id.general-3.2.sentence-2)
— *end note*]
[*Example [3](#id.general-example-3)*:
N::x is interpreted as N::u.x,
where u names the anonymous union variable[.](#id.general-3.2.sentence-3)
— *end example*]
[4](#id.general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1449)
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") that designates a non-static data member or
implicit object member function of a class can only be used:
- [(4.1)](#id.general-4.1)
as part of a class member access
(after any implicit transformation (see above))
in which the
object expression
refers to the member's class
or a class derived from
that class, or
- [(4.2)](#id.general-4.2)
to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")), or
- [(4.3)](#id.general-4.3)
if that [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") designates a non-static data member
and it appears in an unevaluated operand[.](#id.general-4.sentence-1)
[*Example [4](#id.general-example-4)*: struct S {int m;};int i = sizeof(S::m); // OKint j = sizeof(S::m + 42); // OKint S::*k = &[:^^S::m:]; // OK — *end example*]
[5](#id.general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1479)
For an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that denotes an overload set,
overload resolution is performed
to select a unique function ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"))[.](#id.general-5.sentence-1)
[*Note [4](#id.general-note-4)*:
A program cannot refer to a function
with a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") whose [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is not satisfied,
because such functions are never selected by overload resolution[.](#id.general-5.sentence-2)
[*Example [5](#id.general-example-5)*: template<typename T> struct A {static void f(int) requires false;};
void g() { A<int>::f(0); // error: cannot call fvoid (*p1)(int) = A<int>::f; // error: cannot take the address of fdecltype(A<int>::f)* p2 = nullptr; // error: the type decltype(A<int>::f) is invalid}
In each case, the constraints of f are not satisfied[.](#id.general-5.sentence-3)
In the declaration of p2,
those constraints need to be satisfied
even thoughf is an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]")[.](#id.general-5.sentence-4)
— *end example*]
— *end note*]
#### [7.5.5.2](#id.unqual) Unqualified names [[expr.prim.id.unqual]](expr.prim.id.unqual)
[unqualified-id:](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1General[over.oper.general]")
[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")
[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6User-defined literals[over.literal]")
~ [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")
~ [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")
[1](#id.unqual-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1521)
An [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is only
an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") if it has
been suitably declared ([[dcl]](dcl "9Declarations"))
or if it appears as part of a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#id.unqual-1.sentence-1)
[*Note [1](#id.unqual-note-1)*:
For [*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1General[over.oper.general]")*s*, see [[over.oper]](over.oper "12.4Overloaded operators"); for[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")*s*, see [[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions"); for[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6User-defined literals[over.literal]")*s*, see [[over.literal]](over.literal "12.6User-defined literals"); for[*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")*s*, see [[temp.names]](temp.names "13.3Names of template specializations")[.](#id.unqual-1.sentence-2)
A [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") prefixed by ~ denotes the destructor of the type so named;
see [[expr.prim.id.dtor]](#id.dtor "7.5.5.5Destruction")[.](#id.unqual-1.sentence-3)
— *end note*]
[2](#id.unqual-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1537)
A [*component name*](#def:component_name "7.5.5.2Unqualified names[expr.prim.id.unqual]") of an [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") U is
- [(2.1)](#id.unqual-2.1)
U if it is a name or
- [(2.2)](#id.unqual-2.2)
the component name of
the [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") or [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") of U, if any[.](#id.unqual-2.sentence-1)
[*Note [2](#id.unqual-note-2)*:
Other constructs that contain names to look up can have several
component names ([[expr.prim.id.qual]](#id.qual "7.5.5.3Qualified names"), [[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers"), [[dcl.mptr]](dcl.mptr "9.3.4.4Pointers to members"), [[namespace.udecl]](namespace.udecl "9.10The using declaration"), [[temp.param]](temp.param "13.2Template parameters"), [[temp.names]](temp.names "13.3Names of template specializations"), [[temp.res]](temp.res "13.8Name resolution"))[.](#id.unqual-2.sentence-2)
— *end note*]
The [*terminal name*](#def:name,terminal "7.5.5.2Unqualified names[expr.prim.id.unqual]") of a construct is
the component name of that construct that appears lexically last[.](#id.unqual-2.sentence-3)
[3](#id.unqual-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.2Unqualified names[expr.prim.id.unqual]") ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3Unqualified name lookup"))[.](#id.unqual-3.sentence-1)
[4](#id.unqual-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1558)
If
- [(4.1)](#id.unqual-4.1)
the [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") appears in a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") at program point P,
- [(4.2)](#id.unqual-4.2)
the entity is a local entity ([[basic.pre]](basic.pre "6.1Preamble"))
or a variable declared by an [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](#lambda.capture "7.5.6.3Captures")),
- [(4.3)](#id.unqual-4.3)
naming the entity within the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of
the innermost enclosing [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[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*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"), and
- [(4.4)](#id.unqual-4.4)
P is in the function parameter scope,
but not the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]"),
of the innermost such [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[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.5Class 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.6Functions")) of the function call operator of E[.](#id.unqual-4.sentence-1)
[*Note [3](#id.unqual-note-3)*:
If E is not declared mutable,
the type of such an identifier will typically be const qualified[.](#id.unqual-4.sentence-2)
— *end note*]
[5](#id.unqual-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1589)
Otherwise,
if the [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified 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.4Coroutine definitions")),
and the result is that copy[.](#id.unqual-5.sentence-1)
[6](#id.unqual-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1597)
Otherwise,
if the [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") names a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object"))
attached to a function *f* with return type U,
- [(6.1)](#id.unqual-6.1)
if U is “reference to T”,
then the type of the expression isconst T;
- [(6.2)](#id.unqual-6.2)
otherwise,
the type of the expression is const U[.](#id.unqual-6.sentence-1)
[7](#id.unqual-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1613)
Otherwise,
if the [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") appears in the predicate of a contract assertion C ([[basic.contract]](basic.contract "6.11Contract assertions"))
and the entity is
- [(7.1)](#id.unqual-7.1)
a variable
declared outside of C of object type T,
- [(7.2)](#id.unqual-7.2)
a variable or template parameter
declared outside of C of type “reference to T”, or
- [(7.3)](#id.unqual-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[.](#id.unqual-7.sentence-1)
[8](#id.unqual-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1635)
[*Example [1](#id.unqual-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](#id.unqual-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.2Template parameters")),
the type of the expression is const T[.](#id.unqual-9.sentence-1)
[10](#id.unqual-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[.](#id.unqual-10.sentence-1)
[11](#id.unqual-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1695)
[*Note [4](#id.unqual-note-4)*:
The type will be adjusted as described in [[expr.type]](expr.type "7.2.2Type") if it is cv-qualified or is a reference type[.](#id.unqual-11.sentence-1)
— *end note*]
[12](#id.unqual-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.7Structured binding declarations")),
result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")),
data member, or
template parameter object;
and a prvalue otherwise ([[basic.lval]](basic.lval "7.2.1Value category"));
it is a bit-field if the identifier designates a bit-field[.](#id.unqual-12.sentence-1)
[13](#id.unqual-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1714)
If an [*id-expression*](#nt:id-expression "7.5.5.1General[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.7Temporary objects"),
- [(13.1)](#id.unqual-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)](#id.unqual-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[.](#id.unqual-13.sentence-1)
[14](#id.unqual-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1737)
If an [*id-expression*](#nt:id-expression "7.5.5.1General[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.7Temporary objects"),
and the postcondition assertion
is sequenced before the initialization of the result object ([[expr.call]](expr.call "7.6.1.3Function call")),E refers to the most recently initialized such temporary object[.](#id.unqual-14.sentence-1)
[*Example [2](#id.unqual-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](#id.unqual-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1777)
An [*implicitly movable entity*](#def:entity,implicitly_movable "7.5.5.2Unqualified 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[.](#id.unqual-15.sentence-1)
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or[*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") ([[expr.prim.splice]](#splice "7.5.9Expression splicing"))
is [*move-eligible*](#def:move-eligible "7.5.5.2Unqualified names[expr.prim.id.unqual]") if
- [(15.1)](#id.unqual-15.1)
it designates an implicitly movable entity,
- [(15.2)](#id.unqual-15.2)
it is the (possibly parenthesized)
operand of a return ([[stmt.return]](stmt.return "8.8.4The return statement")) orco_return ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")) statement or
of a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") ([[expr.throw]](expr.throw "7.6.18Throwing an exception")), and
- [(15.3)](#id.unqual-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.18Throwing an exception[expr.throw]"),
is not the block scope of
a [*try-block*](except.pre#nt:try-block "14.1Preamble[except.pre]") or [*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]")[.](#id.unqual-15.sentence-2)
#### [7.5.5.3](#id.qual) Qualified names [[expr.prim.id.qual]](expr.prim.id.qual)
[qualified-id:](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]")
[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")
[nested-name-specifier:](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")
::
[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") ::
[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]") ::
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ::
[*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") ::
[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ::
[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") ::
[splice-scope-specifier:](#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")
[*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")
templateopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")
[1](#id.qual-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1832)
The component names of a [*qualified-id*](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") are those of
its [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") and [*unqualified-id*](#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")[.](#id.qual-1.sentence-1)
The component names of a [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") are
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") (if any) and those of its[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"),[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]"),[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]"), and/or[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#id.qual-1.sentence-2)
[2](#id.qual-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1843)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") that is not followed by :: is never interpreted as part of a [*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#id.qual-2.sentence-1)
The keyword template may only be omitted
from the formtemplateopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") :: when the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is preceded by typename[.](#id.qual-2.sentence-2)
[*Example [1](#id.qual-example-1)*: template<int V>struct TCls {static constexpr int s = V; using type = int;};
int v1 = [:^^TCls<1>:]::s;int v2 = template [:^^TCls:]<2>::s; // OK, template binds to [*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")typename [:^^TCls:]<3>::type v3 = 3; // OK, typename binds to the qualified nametemplate [:^^TCls:]<3>::type v4 = 4; // OK, template binds to the [*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")typename template [:^^TCls:]<3>::type v5 = 5; // OK, same as v3[:^^TCls:]<3>::type v6 = 6; // error: unexpected < — *end example*]
[3](#id.qual-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1870)
A [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") is [*declarative*](#def:declarative "7.5.5.3Qualified names[expr.prim.id.qual]") if it is part of
- [(3.1)](#id.qual-3.1)
a [*class-head-name*](class.pre#nt:class-head-name "11.1Preamble[class.pre]"),
- [(3.2)](#id.qual-3.2)
an [*enum-head-name*](dcl.enum#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]"),
- [(3.3)](#id.qual-3.3)
a [*qualified-id*](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") that is the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") of a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]"), or
- [(3.4)](#id.qual-3.4)
a declarative [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#id.qual-3.sentence-1)
A declarative [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") shall not have a [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") or
a [*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#id.qual-3.sentence-2)
A declaration that uses a declarative [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") shall be a friend declaration or
inhabit a scope that contains the entity being redeclared or specialized[.](#id.qual-3.sentence-3)
[4](#id.qual-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1890)
The entity designated by a [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") is determined as follows:
- [(4.1)](#id.qual-4.1)
The [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") :: designates
the global namespace[.](#id.qual-4.1.sentence-1)
- [(4.2)](#id.qual-4.2)
A [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") with a [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") designates the same type designated by the [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]"),
which shall be a class or enumeration type[.](#id.qual-4.2.sentence-1)
- [(4.3)](#id.qual-4.3)
For a [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of
the form [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") ::,
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") shall designate
a class or enumeration type or a namespace[.](#id.qual-4.3.sentence-1)
The [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") designates the same entity
as the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")[.](#id.qual-4.3.sentence-2)
- [(4.4)](#id.qual-4.4)
For a [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of
the formtemplateopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") ::,
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") of
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall designate
a class template or an alias template T[.](#id.qual-4.4.sentence-1)
Letting S be the specialization of T corresponding to the template argument list of
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),S shall either be a class template specialization or
an alias template specialization that denotes a class or enumeration type[.](#id.qual-4.4.sentence-2)
The [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") designates the underlying entity of S[.](#id.qual-4.4.sentence-3)
- [(4.5)](#id.qual-4.5)
If a [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") N is declarative and
has a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") with a template argument list A that involves a template parameter,
let T be the template nominated by N without A[.](#id.qual-4.5.sentence-1)
T shall be a class template[.](#id.qual-4.5.sentence-2)
* [(4.5.1)](#id.qual-4.5.1)
If A is the template argument list ([[temp.arg]](temp.arg "13.4Template arguments")) of
the corresponding [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") H ([[temp.mem]](temp.mem "13.7.3Member templates")),N designates the primary template of T;H shall be equivalent to
the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of T ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#id.qual-4.5.1.sentence-1)
* [(4.5.2)](#id.qual-4.5.2)
Otherwise, N designates the partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")) of T whose template argument list is equivalent to A ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"));
the program is ill-formed if no such partial specialization exists[.](#id.qual-4.5.2.sentence-1)
- [(4.6)](#id.qual-4.6)
Any other [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") designates
the entity denotes by its[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"),[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]"),[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]"), or[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#id.qual-4.6.sentence-1)
If the [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") is not declarative,
the entity shall not be a template[.](#id.qual-4.6.sentence-2)
[5](#id.qual-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1951)
A [*qualified-id*](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") shall not be of the form[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt ~[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") nor of the form[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") :: ~ [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")[.](#id.qual-5.sentence-1)
[6](#id.qual-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1958)
The result of a [*qualified-id*](#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Q is
the entity it denotes ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup"))[.](#id.qual-6.sentence-1)
[7](#id.qual-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1962)
If Q appears
in the predicate of a contract assertion C ([[basic.contract]](basic.contract "6.11Contract assertions"))
and the entity is
- [(7.1)](#id.qual-7.1)
a variable
declared outside of C of object type T,
- [(7.2)](#id.qual-7.2)
a variable
declared outside of C of type “reference to €, or
- [(7.3)](#id.qual-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[.](#id.qual-7.sentence-1)
[8](#id.qual-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1983)
Otherwise, the type of the expression is the type of the result[.](#id.qual-8.sentence-1)
[9](#id.qual-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1986)
The result is an lvalue if the member is
- [(9.1)](#id.qual-9.1)
a function other than a non-static member function,
- [(9.2)](#id.qual-9.2)
a non-static member function
if Q is the operand of a unary & operator,
- [(9.3)](#id.qual-9.3)
a variable,
- [(9.4)](#id.qual-9.4)
a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")), or
- [(9.5)](#id.qual-9.5)
a data member,
and a prvalue otherwise[.](#id.qual-9.sentence-1)
#### [7.5.5.4](#pack.index) Pack indexing expression [[expr.prim.pack.index]](expr.prim.pack.index)
[pack-index-expression:](#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]")
[*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") ... [ [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ]
[1](#pack.index-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2010)
The [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") P in a [*pack-index-expression*](#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]") shall be an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") that denotes a pack[.](#pack.index-1.sentence-1)
[2](#pack.index-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2014)
The [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be
a converted constant expression ([[expr.const]](expr.const "7.7Constant expressions")) of type std::size_t whose value V, termed the index,
is such that ‰¤V<sizeof...(P)[.](#pack.index-2.sentence-1)
[3](#pack.index-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2020)
A [*pack-index-expression*](#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]") is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#pack.index-3.sentence-1)
[4](#pack.index-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2023)
[*Note [1](#pack.index-note-1)*:
A [*pack-index-expression*](#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]") denotes
the Vth element of the pack[.](#pack.index-4.sentence-1)
— *end note*]
#### [7.5.5.5](#id.dtor) Destruction [[expr.prim.id.dtor]](expr.prim.id.dtor)
[1](#id.dtor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2031)
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that denotes the destructor of a type T names the destructor of T if T is a class type ([[class.dtor]](class.dtor "11.4.7Destructors")),
otherwise the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is said
to name a [*pseudo-destructor*](#def:pseudo-destructor "7.5.5.5Destruction[expr.prim.id.dtor]")[.](#id.dtor-1.sentence-1)
[2](#id.dtor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2040)
If the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") names a pseudo-destructor,T shall be a scalar type and
the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") shall appear
as the right operand of a class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access")) that forms
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") of a function call ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#id.dtor-2.sentence-1)
[*Note [1](#id.dtor-note-1)*:
Such a call ends the lifetime of the object ([[expr.call]](expr.call "7.6.1.3Function call"), [[basic.life]](basic.life "6.8.4Lifetime"))[.](#id.dtor-2.sentence-2)
— *end note*]
[3](#id.dtor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2050)
[*Example [1](#id.dtor-example-1)*: struct C { };void f() { C * pc = new C; using C2 = C;
pc->C::~C2(); // OK, destroys *pc C().C::~C(); // undefined behavior: temporary of type C destroyed twiceusing T = int; 0 .T::~T(); // OK, no effect0.T::~T(); // error: 0.T is a [*user-defined-floating-point-literal*](lex.ext#nt:user-defined-floating-point-literal "5.13.9User-defined literals[lex.ext]") ([[lex.ext]](lex.ext "5.13.9User-defined literals"))} — *end example*]
### [7.5.6](#lambda) Lambda expressions [[expr.prim.lambda]](expr.prim.lambda)
#### [7.5.6.1](#lambda.general) General [[expr.prim.lambda.general]](expr.prim.lambda.general)
[lambda-expression:](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")
[*lambda-introducer*](#nt:lambda-introducer "7.5.6.1General[expr.prim.lambda.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[*lambda-introducer*](#nt:lambda-introducer "7.5.6.1General[expr.prim.lambda.general]") < [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") > [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[lambda-introducer:](#nt:lambda-introducer "7.5.6.1General[expr.prim.lambda.general]")
[ [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]")opt ]
[lambda-declarator:](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]")
[*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]") [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")opt
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")opt [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[lambda-specifier:](#nt:lambda-specifier "7.5.6.1General[expr.prim.lambda.general]")
consteval
constexpr
mutable
static
[lambda-specifier-seq:](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]")
[*lambda-specifier*](#nt:lambda-specifier "7.5.6.1General[expr.prim.lambda.general]") [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]")opt
[1](#lambda.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2106)
A [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") provides
a concise way to create a simple function object[.](#lambda.general-1.sentence-1)
[*Example [1](#lambda.general-example-1)*: #include <algorithm>#include <cmath>void abssort(float* x, unsigned N) { std::sort(x, x + N, [](float a, float b) { return std::abs(a) < std::abs(b); });} — *end example*]
[2](#lambda.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2119)
A [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") is a prvalue
whose result object is called the [*closure object*](#def:closure_object "7.5.6.1General[expr.prim.lambda.general]")[.](#lambda.general-2.sentence-1)
[*Note [1](#lambda.general-note-1)*:
A closure object behaves like a [function
object](function.objects "22.10Function objects[function.objects]")[.](#lambda.general-2.sentence-2)
— *end note*]
[3](#lambda.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2127)
An ambiguity can arise
because a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") can end in
an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
which collides with
the [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")[.](#lambda.general-3.sentence-1)
In such cases,
any attributes are treated as[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")[.](#lambda.general-3.sentence-2)
[*Note [2](#lambda.general-note-2)*:
Such ambiguous cases cannot have valid semantics
because the constraint expression would not have type bool[.](#lambda.general-3.sentence-3)
[*Example [2](#lambda.general-example-2)*: auto x = []<class T> requires T::operator int [[some_attribute]] (int) { } — *end example*]
— *end note*]
[4](#lambda.general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2146)
A [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]") shall contain at most one of each [*lambda-specifier*](#nt:lambda-specifier "7.5.6.1General[expr.prim.lambda.general]") and
shall not contain both constexpr and consteval[.](#lambda.general-4.sentence-1)
If the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") contains
an explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
then no [*lambda-specifier*](#nt:lambda-specifier "7.5.6.1General[expr.prim.lambda.general]") in the [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]") shall be mutable or static[.](#lambda.general-4.sentence-2)
The [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]") shall not contain
both mutable and static[.](#lambda.general-4.sentence-3)
If the [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1General[expr.prim.lambda.general]") contains static,
there shall be no [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]")[.](#lambda.general-4.sentence-4)
[*Note [3](#lambda.general-note-3)*:
The trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") is described in [[dcl.decl]](dcl.decl "9.3Declarators")[.](#lambda.general-4.sentence-5)
— *end note*]
[5](#lambda.general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2162)
A [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of
the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]"), if any,
or empty otherwise[.](#lambda.general-5.sentence-1)
If the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") does not include a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]"),
it is considered to be -> auto[.](#lambda.general-5.sentence-2)
[*Note [4](#lambda.general-note-4)*:
In that case, the return type is deduced from return statements
as described in [[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")[.](#lambda.general-5.sentence-3)
— *end note*]
[*Example [3](#lambda.general-example-3)*: auto x1 = [](int i) { return i; }; // OK, return type is intauto x2 = []{ return { 1, 2 }; }; // error: deducing return type from [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")int j;auto x3 = [&]()->auto&& { return j; }; // OK, return type is int& — *end example*]
[6](#lambda.general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2183)
A lambda is a [*generic lambda*](#def:generic_lambda "7.5.6.1General[expr.prim.lambda.general]") if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") has any generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")), or
if the lambda has a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")[.](#lambda.general-6.sentence-1)
[*Example [4](#lambda.general-example-4)*: auto x = [](int i, auto a) { return i; }; // OK, a generic lambdaauto y = [](this auto self, int i) { return i; }; // OK, a generic lambdaauto z = []<class T>(int i) { return i; }; // OK, a generic lambda — *end example*]
#### [7.5.6.2](#lambda.closure) Closure types [[expr.prim.lambda.closure]](expr.prim.lambda.closure)
[1](#lambda.closure-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2198)
The type of a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") (which is also the type of the
closure object) is a unique, unnamed non-union class type,
called the [*closure type*](#def:closure_type "7.5.6.2Closure types[expr.prim.lambda.closure]"),
whose properties are described below[.](#lambda.closure-1.sentence-1)
[2](#lambda.closure-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2204)
The closure type is not complete
until the end of its corresponding [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")[.](#lambda.closure-2.sentence-1)
[3](#lambda.closure-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2208)
The closure type is declared in the smallest block
scope, class scope, or namespace scope that contains the corresponding[*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")[.](#lambda.closure-3.sentence-1)
[*Note [1](#lambda.closure-note-1)*:
This determines the set of namespaces and
classes associated with the closure type ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup"))[.](#lambda.closure-3.sentence-2)
The parameter
types of a [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") do not affect these associated namespaces and
classes[.](#lambda.closure-3.sentence-3)
— *end note*]
[4](#lambda.closure-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2219)
The closure type is not an aggregate type ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"));
it is a structural type ([[temp.param]](temp.param#term.structural.type "13.2Template parameters")) if and only if
the lambda has no [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]")[.](#lambda.closure-4.sentence-1)
An implementation may define the closure type differently from what
is described below provided this does not alter the observable behavior of the program
other than by changing:
- [(4.1)](#lambda.closure-4.1)
the size and/or alignment of the closure type,
- [(4.2)](#lambda.closure-4.2)
whether the closure type is trivially copyable ([[class.prop]](class.prop "11.2Properties of classes")),
- [(4.3)](#lambda.closure-4.3)
whether the closure type is trivially relocatable ([[class.prop]](class.prop "11.2Properties of classes")),
- [(4.4)](#lambda.closure-4.4)
whether the closure type is replaceable ([[class.prop]](class.prop "11.2Properties of classes")), or
- [(4.5)](#lambda.closure-4.5)
whether the closure type is a standard-layout class ([[class.prop]](class.prop "11.2Properties of classes"))[.](#lambda.closure-4.sentence-2)
An implementation shall not add members of rvalue reference type to the closure
type[.](#lambda.closure-4.sentence-3)
[5](#lambda.closure-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2237)
The closure type for a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") has a public
inline function call operator (for a non-generic lambda) or
function call operator template (for a generic lambda) ([[over.call]](over.call "12.4.4Function call"))
whose parameters and return type
are those of the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") and [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") respectively, and whose[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") consists of
the specified [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]"), if any[.](#lambda.closure-5.sentence-1)
The function call operator or the function call operator template are
direct members of the closure type[.](#lambda.closure-5.sentence-2)
The [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") of the function call operator template
is the [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") immediately following< [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") >, if any[.](#lambda.closure-5.sentence-3)
The trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") of the function call operator
or operator template is the [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") of the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]"), if any[.](#lambda.closure-5.sentence-4)
[*Note [2](#lambda.closure-note-2)*:
The function call operator template for a generic lambda can be
an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#lambda.closure-5.sentence-5)
— *end note*]
[*Example [1](#lambda.closure-example-1)*: auto glambda = [](auto a, auto&& b) { return a < b; };bool b = glambda(3, 3.14); // OKauto vglambda = [](auto printer) {return [=](auto&& ... ts) { // OK, ts is a function parameter pack printer(std::forward<decltype(ts)>(ts)...); return [=]() { printer(ts ...); }; };};auto p = vglambda( [](auto v1, auto v2, auto v3){ std::cout << v1 << v2 << v3; } );auto q = p(1, 'a', 3.14); // OK, outputs 1a3.14 q(); // OK, outputs 1a3.14auto fact = [](this auto self, int n) -> int { // OK, explicit object parameterreturn (n <= 1) ? 1 : n * self(n-1);};
std::cout << fact(5); // OK, outputs 120 — *end example*]
[6](#lambda.closure-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2285)
Given a lambda with a [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]"),
the type of the explicit object parameter, if any,
of the lambda's function call operator
(possibly instantiated from a function call operator template)
shall be either:
- [(6.1)](#lambda.closure-6.1)
the closure type,
- [(6.2)](#lambda.closure-6.2)
a class type publicly and unambiguously derived from the closure type, or
- [(6.3)](#lambda.closure-6.3)
a reference to a possibly cv-qualified such type[.](#lambda.closure-6.sentence-1)
[*Example [2](#lambda.closure-example-2)*: struct C {template <typename T> C(T);};
void func(int i) {int x = [=](this auto&&) { return i; }(); // OKint y = [=](this C) { return i; }(); // errorint z = [](this C) { return 42; }(); // OK} — *end example*]
[7](#lambda.closure-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2314)
The function call operator or operator template is
a static member function or static member function template ([[class.static.mfct]](class.static.mfct "11.4.9.2Static member functions"))
if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is followed by static[.](#lambda.closure-7.sentence-1)
Otherwise, it is
a non-static member function or member function template ([[class.mfct.non.static]](class.mfct.non.static "11.4.3Non-static member functions"))
that is declaredconst ([[class.mfct.non.static]](class.mfct.non.static "11.4.3Non-static member functions")) if and only if the[*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is not
followed by mutable and
the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") does not contain
an explicit object parameter[.](#lambda.closure-7.sentence-2)
It is neither virtual nor declared volatile[.](#lambda.closure-7.sentence-3)
Any [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") or [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))
specified on a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") applies to the corresponding function call operator or operator template[.](#lambda.closure-7.sentence-4)
An [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") appertains
to the type of the corresponding function call operator or operator template[.](#lambda.closure-7.sentence-5)
An [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") preceding a [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") appertains to the corresponding function call operator or operator template[.](#lambda.closure-7.sentence-6)
The function call operator or any given operator template specialization
is a constexpr function if either
the corresponding [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is followed by constexpr or consteval, or
it is constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))[.](#lambda.closure-7.sentence-7)
It is an immediate function ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))
if the corresponding [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is followed by consteval[.](#lambda.closure-7.sentence-8)
[*Example [3](#lambda.closure-example-3)*: auto ID = [](auto a) { return a; };static_assert(ID(3) == 3); // OKstruct NonLiteral { NonLiteral(int n) : n(n) { }int n;};static_assert(ID(NonLiteral{3}).n == 3); // error — *end example*]
[8](#lambda.closure-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2358)
[*Example [4](#lambda.closure-example-4)*: auto monoid = [](auto v) { return [=] { return v; }; };auto add = [](auto m1) constexpr {auto ret = m1(); return [=](auto m2) mutable {auto m1val = m1(); auto plus = [=](auto m2val) mutable constexpr{ return m1val += m2val; };
ret = plus(m2()); return monoid(ret); };};constexpr auto zero = monoid(0);constexpr auto one = monoid(1);static_assert(add(one)(zero)() == one()); // OK// Since two below is not declared constexpr, an evaluation of its constexpr member function call operator// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)// in a constant expression.auto two = monoid(2);
assert(two() == 2); // OK, not a constant expression.static_assert(add(one)(one)() == two()); // error: two() is not a constant expressionstatic_assert(add(one)(one)() == monoid(2)()); // OK — *end example*]
[9](#lambda.closure-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2386)
[*Note [3](#lambda.closure-note-3)*:
The function call operator or operator template can be constrained ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))
by a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters")),
a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble")),
or a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#lambda.closure-9.sentence-1)
[*Example [5](#lambda.closure-example-5)*: template <typename T> concept C1 = /* ... */;template <std::size_t N> concept C2 = /* ... */;template <typename A, typename B> concept C3 = /* ... */;
auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)>(T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3<decltype(a4), T2> {// T2 is constrained by a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]").// T1 and T2 are constrained by a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"), and// T2 and the type of a4 are constrained by a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]").}; — *end example*]
— *end note*]
[10](#lambda.closure-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2408)
If all potential references
to a local entity implicitly captured by a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") L occur within the function contract assertions ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))
of the call operator or operator template of L or within [*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9Assertion statement[stmt.contract.assert]")*s* ([[stmt.contract.assert]](stmt.contract.assert "8.9Assertion statement"))
within the body of L,
the program is ill-formed[.](#lambda.closure-10.sentence-1)
[*Note [4](#lambda.closure-note-4)*:
Adding a contract assertion to an existing C++ program cannot
cause additional captures[.](#lambda.closure-10.sentence-2)
— *end note*]
[*Example [6](#lambda.closure-example-6)*: static int i = 0;
void test() {auto f1 = [=] pre(i > 0) {}; // OK, no local entities are captured.int i = 1; auto f2 = [=] pre(i > 0) {}; // error: cannot implicitly capture i hereauto f3 = [i] pre(i > 0) {}; // OK, i is captured explicitly.auto f4 = [=] {contract_assert(i > 0); // error: cannot implicitly capture i here}; auto f5 = [=] {contract_assert(i > 0); // OK, i is referenced elsewhere.(void)i; }; auto f6 = [=] pre( // #1[]{bool x = true; return [=]{ return x; }(); // OK, #1 captures nothing.}()) {}; bool y = true; auto f7 = [=] pre([=]{ return y; }()); // error: outer capture of y is invalid.} — *end example*]
[11](#lambda.closure-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2453)
The closure type for a non-generic [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") with no[*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") and no explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
whose constraints (if any) are satisfied
has a conversion function to pointer to
function with C++ language [linkage](dcl.link "9.12Linkage specifications[dcl.link]") having
the same parameter and return types as the closure type's function call operator[.](#lambda.closure-11.sentence-1)
The conversion is to “pointer to noexcept function”
if the function call operator
has a non-throwing exception specification[.](#lambda.closure-11.sentence-2)
If the function call operator is a static member function,
then the value returned by this conversion function is
a pointer to the function call operator[.](#lambda.closure-11.sentence-3)
Otherwise, the value returned by this conversion function
is a pointer to a function F that, when invoked,
has the same effect as invoking the closure type's function call operator
on a default-constructed instance of the closure type[.](#lambda.closure-11.sentence-4)
F is a constexpr function
if the function call operator is a constexpr function
and is an immediate function
if the function call operator is an immediate function[.](#lambda.closure-11.sentence-5)
[12](#lambda.closure-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2476)
For a generic lambda with no [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") and no explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
the closure type has a
conversion function template to
pointer to function[.](#lambda.closure-12.sentence-1)
The conversion function template has the same invented
template parameter list, and the pointer to function has the same
parameter types, as the function call operator template[.](#lambda.closure-12.sentence-2)
The return type of
the pointer to function shall behave as if it were a[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") denoting the return type of the corresponding
function call operator template specialization[.](#lambda.closure-12.sentence-3)
[13](#lambda.closure-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2488)
[*Note [5](#lambda.closure-note-5)*:
If the generic lambda has no [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") or
the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") contains a placeholder type, return type
deduction of the corresponding function call operator template specialization
has to be done[.](#lambda.closure-13.sentence-1)
The corresponding specialization is that instantiation of the
function call operator template with the same template arguments as those
deduced for the conversion function template[.](#lambda.closure-13.sentence-2)
Consider the following:auto glambda = [](auto a) { return a; };int (*fp)(int) = glambda;
The behavior of the conversion function of glambda above is like
that of the following conversion function:struct Closure {template<class T> auto operator()(T t) const { /* ... */ }template<class T> static auto lambda_call_operator_invoker(T a) {// forwards execution to operator()(a) and therefore has// the same return type deduced/* ... */}template<class T> using fptr_t =decltype(lambda_call_operator_invoker(declval<T>())) (*)(T); template<class T> operator fptr_t<T>() const{ return &lambda_call_operator_invoker; }};
— *end note*]
[*Example [7](#lambda.closure-example-7)*: void f1(int (*)(int)) { }void f2(char (*)(int)) { }void g(int (*)(int)) { } // #1void g(char (*)(char)) { } // #2void h(int (*)(int)) { } // #3void h(char (*)(int)) { } // #4auto glambda = [](auto a) { return a; };
f1(glambda); // OK f2(glambda); // error: ID is not convertible g(glambda); // error: ambiguous h(glambda); // OK, calls #3 since it is convertible from IDint& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK — *end example*]
[14](#lambda.closure-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2539)
If the function call operator template is a static member function template,
then the value returned by
any given specialization of this conversion function template is
a pointer to the corresponding function call operator template specialization[.](#lambda.closure-14.sentence-1)
Otherwise,
the value returned by any given specialization of this conversion function
template is a pointer to a function F that, when invoked, has the same
effect as invoking the generic lambda's corresponding function call operator
template specialization on a default-constructed instance of the closure type[.](#lambda.closure-14.sentence-2)
F is a constexpr function
if the corresponding specialization is a constexpr function andF is an immediate function
if the function call operator template specialization is an immediate function[.](#lambda.closure-14.sentence-3)
[*Note [6](#lambda.closure-note-6)*:
This will result in the implicit instantiation of the generic lambda's body[.](#lambda.closure-14.sentence-4)
The instantiated generic lambda's return type and parameter types need to match
the return type and parameter types of the pointer to function[.](#lambda.closure-14.sentence-5)
— *end note*]
[*Example [8](#lambda.closure-example-8)*: auto GL = [](auto a) { std::cout << a; return a; };int (*GL_int)(int) = GL; // OK, through conversion function template GL_int(3); // OK, same as GL(3) — *end example*]
[15](#lambda.closure-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2566)
The conversion function or conversion function template is public,
constexpr, non-virtual, non-explicit, const, and has a non-throwing [exception
specification](except.spec "14.5Exception specifications[except.spec]")[.](#lambda.closure-15.sentence-1)
[*Example [9](#lambda.closure-example-9)*: auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };auto C = [](auto a) { return a; };
static_assert(Fwd(C,3) == 3); // OK// No specialization of the function call operator template can be constexpr (due to the local static).auto NC = [](auto a) { static int s; return a; };static_assert(Fwd(NC,3) == 3); // error — *end example*]
[16](#lambda.closure-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2583)
The [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") yields
the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")) of the function call operator,
but it is not within the scope of the closure type[.](#lambda.closure-16.sentence-1)
[*Example [10](#lambda.closure-example-10)*: struct S1 {int x, y; int operator()(int); void f() {[=]()->int {return operator()(this->x + y); // equivalent to S1::operator()(this->x + (*this).y)// this has type S1*}; }}; — *end example*]
Unless the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") is
that of a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1Preamble[dcl.pre]") ([[dcl.pre]](dcl.pre "9.1Preamble")),
a variable __func__ is implicitly defined at the beginning of
the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"),
with semantics as described in [[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")[.](#lambda.closure-16.sentence-2)
[17](#lambda.closure-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2607)
The closure type associated with a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") has no
default constructor
if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") has a [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") and a defaulted default constructor otherwise[.](#lambda.closure-17.sentence-1)
It has a defaulted copy constructor and a defaulted move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"))[.](#lambda.closure-17.sentence-2)
It has a deleted copy assignment operator if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") has a [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") and defaulted copy and move assignment
operators otherwise ([[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator"))[.](#lambda.closure-17.sentence-3)
[*Note [7](#lambda.closure-note-7)*:
These special member functions are implicitly defined as
usual, which can result in them being defined as deleted[.](#lambda.closure-17.sentence-4)
— *end note*]
[18](#lambda.closure-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2621)
The closure type associated with a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") has an
implicitly-declared destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#lambda.closure-18.sentence-1)
[19](#lambda.closure-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2625)
A member of a closure type shall not be[explicitly instantiated](temp.explicit "13.9.3Explicit instantiation[temp.explicit]"),[explicitly specialized](temp.expl.spec "13.9.4Explicit specialization[temp.expl.spec]"), or
named in a [friend declaration](class.friend "11.8.4Friends[class.friend]")[.](#lambda.closure-19.sentence-1)
#### [7.5.6.3](#lambda.capture) Captures [[expr.prim.lambda.capture]](expr.prim.lambda.capture)
[lambda-capture:](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]")
[*capture-list*](#nt:capture-list "7.5.6.3Captures[expr.prim.lambda.capture]")
[*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") , [*capture-list*](#nt:capture-list "7.5.6.3Captures[expr.prim.lambda.capture]")
[capture-default:](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]")
&
=
[capture-list:](#nt:capture-list "7.5.6.3Captures[expr.prim.lambda.capture]")
[*capture*](#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[*capture-list*](#nt:capture-list "7.5.6.3Captures[expr.prim.lambda.capture]") , [*capture*](#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[capture:](#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[simple-capture:](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ...opt
& [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ...opt
this
* this
[init-capture:](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]")
...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")
& ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")
[1](#lambda.capture-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2672)
The body of a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") may refer to local entities
of enclosing scopes by capturing those entities, as described
below[.](#lambda.capture-1.sentence-1)
[2](#lambda.capture-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2677)
If a [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") includes a [*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") that
is &, no identifier in a [*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]") of that[*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") shall be preceded
by &[.](#lambda.capture-2.sentence-1)
If a [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") includes a[*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") that is =, each[*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]") of that [*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]") shall
be of the form
“& [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ...opt”,
“this”,
or “* this”[.](#lambda.capture-2.sentence-2)
[*Note [1](#lambda.capture-note-1)*:
The form [&,this] is redundant but accepted
for compatibility with C++ 2014[.](#lambda.capture-2.sentence-3)
— *end note*]
Ignoring appearances in[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")*s* of [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]")*s*, an identifier orthis shall not appear more than once in a[*lambda-capture*](#nt:lambda-capture "7.5.6.3Captures[expr.prim.lambda.capture]")[.](#lambda.capture-2.sentence-4)
[*Example [1](#lambda.capture-example-1)*: struct S2 { void f(int i); };void S2::f(int i) {[&, i]{ }; // OK[&, this, i]{ }; // OK, equivalent to [&, i][&, &i]{ }; // error: i preceded by & when & is the default[=, *this]{ }; // OK[=, this]{ }; // OK, equivalent to [=][i, i]{ }; // error: i repeated[this, *this]{ }; // error: this appears twice} — *end example*]
[3](#lambda.capture-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2711)
A [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") shall not have
a [*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") or [*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]") in its [*lambda-introducer*](#nt:lambda-introducer "7.5.6.1General[expr.prim.lambda.general]") unless
- [(3.1)](#lambda.capture-3.1)
its innermost enclosing scope is a block scope ([[basic.scope.block]](basic.scope.block "6.4.3Block scope")),
- [(3.2)](#lambda.capture-3.2)
it appears within a default member initializer
and its innermost enclosing scope is
the corresponding class scope ([[basic.scope.class]](basic.scope.class "6.4.7Class scope")), or
- [(3.3)](#lambda.capture-3.3)
it appears within a contract assertion
and its innermost enclosing scope
is the corresponding contract-assertion scope ([[basic.scope.contract]](basic.scope.contract "6.4.10Contract-assertion scope"))[.](#lambda.capture-3.sentence-1)
[4](#lambda.capture-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2729)
The [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in a [*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]") shall denote a local entity ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3Unqualified name lookup"), [[basic.pre]](basic.pre "6.1Preamble"))[.](#lambda.capture-4.sentence-1)
The [*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]")*s* this and * this denote the local entity *this[.](#lambda.capture-4.sentence-2)
An entity that is designated by a[*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]") is said to be [*explicitly captured*](#def:explicitly_captured "7.5.6.3Captures[expr.prim.lambda.capture]")[.](#lambda.capture-4.sentence-3)
[5](#lambda.capture-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2738)
If an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in a [*capture*](#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]") appears
as the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") of a parameter of
the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]")'s [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") or as the name of a template parameter of
the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")'s [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]"),
the program is ill-formed[.](#lambda.capture-5.sentence-1)
[*Example [2](#lambda.capture-example-2)*: void f() {int x = 0; auto g = [x](int x) { return 0; }; // error: parameter and [*capture*](#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]") have the same nameauto h = [y = 0]<typename y>(y) { return 0; }; // error: template parameter and [*capture*](#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]")// have the same name} — *end example*]
[6](#lambda.capture-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2756)
An [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") inhabits
the lambda scope ([[basic.scope.lambda]](basic.scope.lambda "6.4.5Lambda scope"))
of the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")[.](#lambda.capture-6.sentence-1)
An [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") without ellipsis
behaves as if it declares and explicitly captures a variable of
the form “auto [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") ;”, except that:
- [(6.1)](#lambda.capture-6.1)
if the capture is by copy (see below), the non-static data member
declared for the capture and the variable are treated as two different ways
of referring to the same object, which has the lifetime of the non-static
data member, and no additional copy and destruction is performed, and
- [(6.2)](#lambda.capture-6.2)
if the capture is by reference, the variable's lifetime ends when the
closure object's lifetime ends[.](#lambda.capture-6.sentence-2)
[*Note [2](#lambda.capture-note-2)*:
This enables an [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") like
“x = std::move(x)”; the second “€ must bind to a
declaration in the surrounding context[.](#lambda.capture-6.sentence-3)
— *end note*]
[*Example [3](#lambda.capture-example-3)*: int x = 4;auto y = [&r = x, x = x+1]()->int { r += 2; return x+2; }(); // Updates ::x to 6, and initializes y to 7.auto z = [a = 42](int a) { return 1; }; // error: parameter and conceptual local variable have the same nameauto counter = [i=0]() mutable -> decltype(i) { // OK, returns intreturn i++;}; — *end example*]
[7](#lambda.capture-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2791)
For the purposes of lambda capture,
an expression potentially references local entities as follows:
- [(7.1)](#lambda.capture-7.1)
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that names a local entity
potentially references that entity;
an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that names
one or more non-static class members
and does not form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators"))
potentially references *this[.](#lambda.capture-7.1.sentence-1)
[*Note [3](#lambda.capture-note-3)*:
This occurs even if overload resolution
selects a static member function for the [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]")[.](#lambda.capture-7.1.sentence-2)
— *end note*]
- [(7.2)](#lambda.capture-7.2)
A this expression potentially references *this[.](#lambda.capture-7.2.sentence-1)
- [(7.3)](#lambda.capture-7.3)
A [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") potentially references
the local entities named by its [*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]")*s*[.](#lambda.capture-7.3.sentence-1)
If an expression potentially references a local entity
within a scope in which it is odr-usable ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")),
and the expression would be potentially evaluated
if the effect of any enclosing typeid expressions ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")) were ignored,
the entity is said to be [*implicitly captured*](#def:capture,implicit "7.5.6.3Captures[expr.prim.lambda.capture]") by each intervening [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") with an associated[*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") that does not explicitly capture it[.](#lambda.capture-7.sentence-2)
The implicit capture of *this is deprecated when the[*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") is =; see [[depr.capture.this]](depr.capture.this "D.3Implicit capture of *this by reference")[.](#lambda.capture-7.sentence-3)
[*Example [4](#lambda.capture-example-4)*: void f(int, const int (&)[2] = {}); // #1void f(const int&, const int (&)[1]); // #2void test() {const int x = 17; auto g = [](auto a) { f(x); // OK, calls #1, does not capture x}; auto g1 = [=](auto a) { f(x); // OK, calls #1, captures x}; auto g2 = [=](auto a) {int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK, captures x, can call #1 or #2}; auto g3 = [=](auto a) {typeid(a + x); // captures x regardless of whether a + x is an unevaluated operand};}
Within g1, an implementation can optimize away
the capture of x as it is not odr-used[.](#lambda.capture-7.sentence-4)
— *end example*]
[*Note [4](#lambda.capture-note-4)*:
The set of captured entities is determined syntactically,
and entities are implicitly captured
even if the expression denoting a local entity
is within a discarded statement ([[stmt.if]](stmt.if "8.5.2The if statement"))[.](#lambda.capture-7.sentence-5)
[*Example [5](#lambda.capture-example-5)*: template<bool B>void f(int n) {[=](auto a) {if constexpr (B && sizeof(a) > 4) {(void)n; // captures n regardless of the value of B and sizeof(int)}}(0);} — *end example*]
— *end note*]
[8](#lambda.capture-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2870)
An entity is [*captured*](#def:captured "7.5.6.3Captures[expr.prim.lambda.capture]") if it is captured explicitly or implicitly[.](#lambda.capture-8.sentence-1)
An entity
captured by a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) by
the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")[.](#lambda.capture-8.sentence-2)
[*Note [5](#lambda.capture-note-5)*:
As a consequence, if a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") explicitly captures an entity that is not odr-usable,
the program is ill-formed ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#lambda.capture-8.sentence-3)
— *end note*]
[*Example [6](#lambda.capture-example-6)*:
[🔗](#:Bond,James_Bond)
void f1(int i) {int const N = 20; auto m1 = [=]{int const M = 30; auto m2 = [i]{int x[N][M]; // OK, N and M are not odr-used x[0][0] = i; // OK, i is explicitly captured by m2 and implicitly captured by m1}; }; struct s1 {int f; void work(int n) {int m = n*n; int j = 40; auto m3 = [this,m] {auto m4 = [&,j] { // error: j not odr-usable due to intervening lambda m3int x = n; // error: n is odr-used but not odr-usable due to intervening lambda m3 x += m; // OK, m implicitly captured by m4 and explicitly captured by m3 x += i; // error: i is odr-used but not odr-usable// due to intervening function and class scopes x += f; // OK, this captured implicitly by m4 and explicitly by m3}; }; }};}struct s2 {double ohseven = .007; auto f() {return [this] {return [*this] {return ohseven; // OK}; }(); }auto g() {return [] {return [*this] { }; // error: *this not captured by outer [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")}(); }}; — *end example*]
[9](#lambda.capture-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2927)
[*Note [6](#lambda.capture-note-6)*:
Because local entities are not
odr-usable within a default argument ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")),
a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") appearing in a default argument
cannot implicitly or explicitly capture any local entity[.](#lambda.capture-9.sentence-1)
Such a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") can still have an [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") if
any full-expression in its [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") satisfies the constraints of an expression appearing in
a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#lambda.capture-9.sentence-2)
— *end note*]
[*Example [7](#lambda.capture-example-7)*: void f2() {int i = 1; void g1(int = ([i]{ return i; })()); // errorvoid g2(int = ([i]{ return 0; })()); // errorvoid g3(int = ([=]{ return i; })()); // errorvoid g4(int = ([=]{ return 0; })()); // OKvoid g5(int = ([]{ return sizeof i; })()); // OKvoid g6(int = ([x=1]{ return x; })()); // OKvoid g7(int = ([x=i]{ return x; })()); // error} — *end example*]
[10](#lambda.capture-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2954)
An entity is [*captured by copy*](#def:captured,by_copy "7.5.6.3Captures[expr.prim.lambda.capture]") if
- [(10.1)](#lambda.capture-10.1)
it is implicitly captured,
the [*capture-default*](#nt:capture-default "7.5.6.3Captures[expr.prim.lambda.capture]") is =, and
the captured entity is not *this, or
- [(10.2)](#lambda.capture-10.2)
it is explicitly captured with a capture that is not of the formthis,& [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ...opt, or& ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#lambda.capture-10.sentence-1)
For each entity captured by copy, an
unnamed non-static data member is declared in the closure type[.](#lambda.capture-10.sentence-2)
The declaration order of
these members is unspecified[.](#lambda.capture-10.sentence-3)
The type of such a data member is
the referenced type if the entity is a reference to an object,
an lvalue reference to the referenced function type if the entity is a reference to a function, or
the type of the corresponding captured entity otherwise[.](#lambda.capture-10.sentence-4)
A member of an anonymous union shall not be captured by copy[.](#lambda.capture-10.sentence-5)
[11](#lambda.capture-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L2975)
Every [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") within the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of a[*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") that is an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) of an
entity captured by copy is transformed into an access to the corresponding unnamed data
member of the closure type[.](#lambda.capture-11.sentence-1)
[*Note [7](#lambda.capture-note-7)*:
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that is not an odr-use refers to
the original entity, never to a member of the closure type[.](#lambda.capture-11.sentence-2)
However, such
an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") can still cause the implicit capture of the
entity[.](#lambda.capture-11.sentence-3)
— *end note*]
If *this is captured by copy, each expression that odr-uses *this is
transformed to instead refer to the corresponding unnamed data member of the closure type[.](#lambda.capture-11.sentence-4)
[*Example [8](#lambda.capture-example-8)*: void f(const int*);void g() {const int N = 10; [=] {int arr[N]; // OK, not an odr-use, refers to variable with automatic storage duration f(&N); // OK, causes N to be captured; &N points to// the corresponding member of the closure type};} — *end example*]
[12](#lambda.capture-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3003)
An entity is [*captured by reference*](#def:captured,by_reference "7.5.6.3Captures[expr.prim.lambda.capture]") if it is implicitly or explicitly
captured but not captured by copy[.](#lambda.capture-12.sentence-1)
It is unspecified whether additional unnamed
non-static data members are declared in the closure type for entities captured by
reference[.](#lambda.capture-12.sentence-2)
If declared, such non-static data members shall be of literal type[.](#lambda.capture-12.sentence-3)
[*Example [9](#lambda.capture-example-9)*: // The inner closure type must be a literal type regardless of how reference captures are represented.static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4); — *end example*]
A bit-field or a member of an anonymous union
shall not be captured by reference[.](#lambda.capture-12.sentence-4)
[13](#lambda.capture-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3018)
An [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") within
the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") that is an odr-use of a reference captured by reference
refers to the entity to which the captured reference is bound and
not to the captured reference[.](#lambda.capture-13.sentence-1)
[*Note [8](#lambda.capture-note-8)*:
The validity of such captures is determined by
the lifetime of the object to which the reference refers,
not by the lifetime of the reference itself[.](#lambda.capture-13.sentence-2)
— *end note*]
[*Example [10](#lambda.capture-example-10)*: auto h(int &r) {return [&] {++r; // Valid after h returns if the lifetime of the// object to which r is bound has not ended};} — *end example*]
[14](#lambda.capture-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3040)
If a [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") m2 captures an entity and that entity is
captured by an immediately enclosing [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")m1, thenm2's capture is transformed as follows:
- [(14.1)](#lambda.capture-14.1)
If m1 captures the entity by copy,m2 captures the corresponding
non-static data member of m1's closure type;
if m1 is not mutable, the non-static data member is considered to be const-qualified[.](#lambda.capture-14.1.sentence-1)
- [(14.2)](#lambda.capture-14.2)
If m1 captures the entity by reference,m2 captures the same
entity captured by m1[.](#lambda.capture-14.2.sentence-1)
[*Example [11](#lambda.capture-example-11)*:
The nested [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* and invocations below will output123234[.](#lambda.capture-14.sentence-2)
int a = 1, b = 1, c = 1;auto m1 = [a, &b, &c]() mutable {auto m2 = [a, b, &c]() mutable { std::cout << a << b << c;
a = 4; b = 4; c = 4; };
a = 3; b = 3; c = 3;
m2();};
a = 2; b = 2; c = 2;
m1();
std::cout << a << b << c; — *end example*]
[15](#lambda.capture-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3073)
When the [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") is evaluated, the entities that are
captured by copy are used to direct-initialize each corresponding non-static data member
of the resulting closure object, and the non-static data members corresponding to the[*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]")*s* are initialized as indicated by the corresponding[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") (which may be copy- or direct-initialization)[.](#lambda.capture-15.sentence-1)
(For array members, the array elements are
direct-initialized in increasing subscript order[.](#lambda.capture-15.sentence-2))
These initializations are performed
in the (unspecified) order in which the non-static data members are declared[.](#lambda.capture-15.sentence-3)
[*Note [9](#lambda.capture-note-9)*:
This ensures that the destructions will occur in the reverse order of the constructions[.](#lambda.capture-15.sentence-4)
— *end note*]
[16](#lambda.capture-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3085)
[*Note [10](#lambda.capture-note-10)*:
If a non-reference entity is implicitly or explicitly captured by reference,
invoking the function call operator of the corresponding [*lambda-expression*](#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") after the lifetime of the entity has ended is likely to result in undefined behavior[.](#lambda.capture-16.sentence-1)
— *end note*]
[17](#lambda.capture-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3092)
A [*simple-capture*](#nt:simple-capture "7.5.6.3Captures[expr.prim.lambda.capture]") containing an ellipsis is a pack
expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#lambda.capture-17.sentence-1)
An [*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") containing an ellipsis is a pack
expansion that declares an[*init-capture*](#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#lambda.capture-17.sentence-2)
[*Example [12](#lambda.capture-example-12)*: template<class... Args>void f(Args... args) {auto lm = [&, args...] { return g(args...); };
lm(); auto lm2 = [...xs=std::move(args)] { return g(xs...); };
lm2();} — *end example*]
### [7.5.7](#fold) Fold expressions [[expr.prim.fold]](expr.prim.fold)
[1](#fold-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3116)
A fold expression performs a fold of a
pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")) over a binary operator[.](#fold-1.sentence-1)
[fold-expression:](#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]")
( [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") ... )
( ... [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") )
( [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") ... [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") )
[fold-operator:](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") one of
+ - * / % ^ & | << >>
+= -= *= /= %= ^= &= |= <<= >>= =
== != < > <= >= && || , .* ->*
[2](#fold-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3136)
An expression of the form(... *op* e) where *op* is a [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is called a [*unary left fold*](#def:unary_left_fold "7.5.7Fold expressions[expr.prim.fold]")[.](#fold-2.sentence-1)
An expression of the form(e *op* ...) where *op* is a [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is called a [*unary right fold*](#def:unary_right_fold "7.5.7Fold expressions[expr.prim.fold]")[.](#fold-2.sentence-2)
Unary left folds and unary right folds
are collectively called [*unary folds*](#def:unary_fold "7.5.7Fold expressions[expr.prim.fold]")[.](#fold-2.sentence-3)
In a unary fold,
the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") shall contain an unexpanded pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#fold-2.sentence-4)
[3](#fold-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3152)
An expression of the form(e1 *op1* ... *op2* e2) where *op1* and *op2* are [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]")*s* is called a [*binary fold*](#def:binary_fold "7.5.7Fold expressions[expr.prim.fold]")[.](#fold-3.sentence-1)
In a binary fold,*op1* and *op2* shall be the same [*fold-operator*](#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]"),
and either e1 shall contain an unexpanded pack
or e2 shall contain an unexpanded pack,
but not both[.](#fold-3.sentence-2)
If e2 contains an unexpanded pack,
the expression is called a [*binary left fold*](#def:binary_left_fold "7.5.7Fold expressions[expr.prim.fold]")[.](#fold-3.sentence-3)
If e1 contains an unexpanded pack,
the expression is called a [*binary right fold*](#def:binary_right_fold "7.5.7Fold expressions[expr.prim.fold]")[.](#fold-3.sentence-4)
[*Example [1](#fold-example-1)*: template<typename ...Args>bool f(Args ...args) {return (true && ... && args); // OK}template<typename ...Args>bool f(Args ...args) {return (args + ... + args); // error: both operands contain unexpanded packs} — *end example*]
[4](#fold-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3184)
A fold expression is a pack expansion[.](#fold-4.sentence-1)
### [7.5.8](#req) Requires expressions [[expr.prim.req]](expr.prim.req)
#### [7.5.8.1](#req.general) General [[expr.prim.req.general]](expr.prim.req.general)
[1](#req.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3193)
A [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") provides a concise way to express
requirements on template arguments
that can be checked by [name lookup](basic.lookup "6.5Name lookup[basic.lookup]") or by checking properties of types and expressions[.](#req.general-1.sentence-1)
[requires-expression:](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]")
requires [*requirement-parameter-list*](#nt:requirement-parameter-list "7.5.8.1General[expr.prim.req.general]")opt [*requirement-body*](#nt:requirement-body "7.5.8.1General[expr.prim.req.general]")
[requirement-parameter-list:](#nt:requirement-parameter-list "7.5.8.1General[expr.prim.req.general]")
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") )
[requirement-body:](#nt:requirement-body "7.5.8.1General[expr.prim.req.general]")
{ [*requirement-seq*](#nt:requirement-seq "7.5.8.1General[expr.prim.req.general]") }
[requirement-seq:](#nt:requirement-seq "7.5.8.1General[expr.prim.req.general]")
[*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]") [*requirement-seq*](#nt:requirement-seq "7.5.8.1General[expr.prim.req.general]")opt
[requirement:](#nt:requirement "7.5.8.1General[expr.prim.req.general]")
[*simple-requirement*](#nt:simple-requirement "7.5.8.2Simple requirements[expr.prim.req.simple]")
[*type-requirement*](#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]")
[*compound-requirement*](#nt:compound-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]")
[*nested-requirement*](#nt:nested-requirement "7.5.8.5Nested requirements[expr.prim.req.nested]")
[2](#req.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3228)
A [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") is a prvalue of type bool whose value is described below[.](#req.general-2.sentence-1)
[3](#req.general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3232)
[*Example [1](#req.general-example-1)*:
A common use of [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]")*s* is to define
requirements in concepts such as the one below:template<typename T>concept R = requires (T i) {typename T::type; {*i} -> std::[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const typename T::type&>; };
A [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") can also be used in a[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble")) as a way of writing ad hoc
constraints on template arguments such as the one below:template<typename T>requires requires (T x) { x + x; } T add(T a, T b) { return a + b; }
The first requires introduces the[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"), and the second
introduces the [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]")[.](#req.general-3.sentence-3)
— *end example*]
[4](#req.general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3256)
A [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") may introduce local parameters using a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")[.](#req.general-4.sentence-1)
A local parameter of a [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") shall not have a
default argument[.](#req.general-4.sentence-2)
The type of such a parameter is determined as specified for
a function parameter in [[dcl.fct]](dcl.fct "9.3.4.6Functions")[.](#req.general-4.sentence-3)
These parameters have no linkage, storage, or lifetime; they are only used
as notation for the purpose of defining [*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]")*s*[.](#req.general-4.sentence-4)
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of a[*requirement-parameter-list*](#nt:requirement-parameter-list "7.5.8.1General[expr.prim.req.general]") shall not terminate with an ellipsis[.](#req.general-4.sentence-5)
[*Example [2](#req.general-example-2)*: template<typename T>concept C = requires(T t, ...) { // error: terminates with an ellipsis t;};template<typename T>concept C2 = requires(T p[2]) {(decltype(p))nullptr; // OK, p has type “pointer to T''}; — *end example*]
[5](#req.general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3281)
The substitution of template arguments into a [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") can result in
the formation of invalid types or expressions in the immediate context of
its [*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]")*s* ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")) or
the violation of the semantic constraints of those [*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]")*s*[.](#req.general-5.sentence-1)
In such cases, the [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") evaluates to false;
it does not cause the program to be ill-formed[.](#req.general-5.sentence-2)
The substitution and semantic constraint checking
proceeds in lexical order and stops when a condition that
determines the result of the [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") is encountered[.](#req.general-5.sentence-3)
If substitution (if any) and semantic constraint checking succeed,
the [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") evaluates to true[.](#req.general-5.sentence-4)
[*Note [1](#req.general-note-1)*:
If a [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") contains invalid types or expressions in
its [*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]")*s*, and it does not appear within the declaration of a templated
entity, then the program is ill-formed[.](#req.general-5.sentence-5)
— *end note*]
If the substitution of template arguments into a [*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]") would always result in a substitution failure, the program is ill-formed;
no diagnostic required[.](#req.general-5.sentence-6)
[*Example [3](#req.general-example-3)*: template<typename T> concept C =requires {new decltype((void)T{}); // ill-formed, no diagnostic required}; — *end example*]
#### [7.5.8.2](#req.simple) Simple requirements [[expr.prim.req.simple]](expr.prim.req.simple)
[simple-requirement:](#nt:simple-requirement "7.5.8.2Simple requirements[expr.prim.req.simple]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ;
[1](#req.simple-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3319)
A [*simple-requirement*](#nt:simple-requirement "7.5.8.2Simple requirements[expr.prim.req.simple]") asserts
the validity of an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")[.](#req.simple-1.sentence-1)
The [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is an unevaluated operand[.](#req.simple-1.sentence-2)
[*Note [1](#req.simple-note-1)*:
The enclosing [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") will evaluate to false if substitution of template arguments into the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") fails[.](#req.simple-1.sentence-3)
— *end note*]
[*Example [1](#req.simple-example-1)*: template<typename T> concept C =requires (T a, T b) { a + b; // C<T> is true if a + b is a valid expression}; — *end example*]
[2](#req.simple-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3336)
A [*requirement*](#nt:requirement "7.5.8.1General[expr.prim.req.general]") that starts with a requires token
is never interpreted as a [*simple-requirement*](#nt:simple-requirement "7.5.8.2Simple requirements[expr.prim.req.simple]")[.](#req.simple-2.sentence-1)
[*Note [2](#req.simple-note-2)*:
This simplifies distinguishing between a [*simple-requirement*](#nt:simple-requirement "7.5.8.2Simple requirements[expr.prim.req.simple]") and a [*nested-requirement*](#nt:nested-requirement "7.5.8.5Nested requirements[expr.prim.req.nested]")[.](#req.simple-2.sentence-2)
— *end note*]
#### [7.5.8.3](#req.type) Type requirements [[expr.prim.req.type]](expr.prim.req.type)
[type-requirement:](#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]")
typename [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") ;
typename [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")
typename [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")
[1](#req.type-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3354)
A [*type-requirement*](#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]") asserts the validity of a type[.](#req.type-1.sentence-1)
The component names of a [*type-requirement*](#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]") are those of its[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") (if any) and[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") (if any)[.](#req.type-1.sentence-2)
[*Note [1](#req.type-note-1)*:
The enclosing [*requires-expression*](#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") will evaluate to false if substitution of template arguments fails[.](#req.type-1.sentence-3)
— *end note*]
[*Example [1](#req.type-example-1)*: template<typename T, typename T::type = 0> struct S;template<typename T> using Ref = T&;
template<typename T> concept C = requires {typename T::inner; // required nested member nametypename S<T>; // required valid ([[temp.names]](temp.names "13.3Names of template specializations")) [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"); fails if T::type does not exist as a type// to which 0 can be implicitly convertedtypename Ref<T>; // required alias template substitution, fails if T is voidtypename [:T::r1:]; // fails if T::r1 is not a reflection of a typetypename [:T::r2:]<int>; // fails if T::r2 is not a reflection of a template Z for which Z<int> is a type}; — *end example*]
[2](#req.type-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3379)
A [*type-requirement*](#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]") that names a class template specialization
does not require that type to be complete ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General"))[.](#req.type-2.sentence-1)
#### [7.5.8.4](#req.compound) Compound requirements [[expr.prim.req.compound]](expr.prim.req.compound)
[compound-requirement:](#nt:compound-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]")
{ [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") } noexceptopt [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]")opt ;
[return-type-requirement:](#nt:return-type-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]")
-> [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")
[1](#req.compound-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3396)
A [*compound-requirement*](#nt:compound-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]") asserts properties
of the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") E[.](#req.compound-1.sentence-1)
The [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is an unevaluated operand[.](#req.compound-1.sentence-2)
Substitution
of template arguments (if any) and verification of
semantic properties proceed in the following order:
- [(1.1)](#req.compound-1.1)
Substitution of template arguments (if any)
into the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is performed[.](#req.compound-1.1.sentence-1)
- [(1.2)](#req.compound-1.2)
If the noexcept specifier is present,E shall not be a potentially-throwing expression ([[except.spec]](except.spec "14.5Exception specifications"))[.](#req.compound-1.2.sentence-1)
- [(1.3)](#req.compound-1.3)
If the [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]") is present, then:
* [(1.3.1)](#req.compound-1.3.1)
Substitution of template arguments (if any)
into the [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]") is performed[.](#req.compound-1.3.1.sentence-1)
* [(1.3.2)](#req.compound-1.3.2)
The immediately-declared constraint ([[temp.param]](temp.param "13.2Template parameters"))
of the [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") for decltype((E)) shall be satisfied[.](#req.compound-1.3.2.sentence-1)
[*Example [1](#req.compound-example-1)*:
Given concepts C and D,requires {{ E1 } -> C; { E2 } -> D<A1, ⋯, An>;}; is equivalent torequires { E1; requires C<decltype((E1))>;
E2; requires D<decltype((E2)), A1, ⋯, An>;}; (including in the case where n is zero)[.](#req.compound-1.3.sentence-2)
— *end example*]
[2](#req.compound-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3442)
[*Example [2](#req.compound-example-2)*: template<typename T> concept C1 = requires(T x) {{x++};};
The [*compound-requirement*](#nt:compound-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]") in C1 requires that x++ is a valid expression[.](#req.compound-2.sentence-1)
It is equivalent to the [*simple-requirement*](#nt:simple-requirement "7.5.8.2Simple requirements[expr.prim.req.simple]")x++;[.](#req.compound-2.sentence-2)
template<typename T> concept C2 = requires(T x) {{*x} -> std::[same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<typename T::inner>;};
The [*compound-requirement*](#nt:compound-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]") in C2 requires that *x is a valid expression,
that typename T::inner is a valid type, and
that std::[same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<decltype((*x)), typename T::inner> is satisfied[.](#req.compound-2.sentence-3)
template<typename T> concept C3 =requires(T x) {{g(x)} noexcept; };
The [*compound-requirement*](#nt:compound-requirement "7.5.8.4Compound requirements[expr.prim.req.compound]") in C3 requires that g(x) is a valid expression and
that g(x) is non-throwing[.](#req.compound-2.sentence-4)
— *end example*]
#### [7.5.8.5](#req.nested) Nested requirements [[expr.prim.req.nested]](expr.prim.req.nested)
[nested-requirement:](#nt:nested-requirement "7.5.8.5Nested requirements[expr.prim.req.nested]")
requires [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") ;
[1](#req.nested-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3485)
A [*nested-requirement*](#nt:nested-requirement "7.5.8.5Nested requirements[expr.prim.req.nested]") can be used
to specify additional constraints in terms of local parameters[.](#req.nested-1.sentence-1)
The [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") shall be satisfied ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))
by the substituted template arguments, if any[.](#req.nested-1.sentence-2)
Substitution of template arguments into a [*nested-requirement*](#nt:nested-requirement "7.5.8.5Nested requirements[expr.prim.req.nested]") does not result in substitution into the [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") other than as specified in [[temp.constr.constr]](temp.constr.constr "13.5.2Constraints")[.](#req.nested-1.sentence-3)
[*Example [1](#req.nested-example-1)*:
template<typename U> concept C = sizeof(U) == 1;
template<typename T> concept D = requires (T t) {requires C<decltype (+t)>;};D<T> is satisfied if sizeof(decltype (+t)) == 1 ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3Atomic constraints"))[.](#req.nested-1.sentence-4)
— *end example*]
### [7.5.9](#splice) Expression splicing [[expr.prim.splice]](expr.prim.splice)
[splice-expression:](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")
[*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")
template [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")
template [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")
[1](#splice-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3516)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") immediately followed by :: or preceded by typename is never interpreted as part of a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")[.](#splice-1.sentence-1)
[*Example [1](#splice-example-1)*: struct S { static constexpr int a = 1; };template<typename> struct TCls { static constexpr int b = 2; };
constexpr int c = [:^^S:]::a; // OK, [:^^S:] is not an expressionconstexpr int d = template [:^^TCls:]<int>::b; // OK, template [:^^TCls:]<int> is not an expressiontemplate<auto V> constexpr int e = [:V:]; // OKconstexpr int f = template [:^^e:]<^^S::a>; // OKconstexpr auto g = typename [:^^int:](42); // OK, typename [:^^int:] is a [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]")constexpr auto h = ^^g;constexpr auto i = e<[:^^h:]>; // error: unparenthesized [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") used as template argumentconstexpr auto j = e<([:^^h:])>; // OK — *end example*]
[2](#splice-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3539)
For a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") of the form [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]"),
let S be the construct designated by [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")[.](#splice-2.sentence-1)
- [(2.1)](#splice-2.1)
The expression is ill-formed if S is
* [(2.1.1)](#splice-2.1.1)
a constructor,
* [(2.1.2)](#splice-2.1.2)
a destructor,
* [(2.1.3)](#splice-2.1.3)
an unnamed bit-field, or
* [(2.1.4)](#splice-2.1.4)
a local entity ([[basic.pre]](basic.pre "6.1Preamble")) such that
+
[(2.1.4.1)](#splice-2.1.4.1)
there is a lambda scope that intervenes
between the expression and the point at which S was introduced and
+
[(2.1.4.2)](#splice-2.1.4.2)
the expression would be potentially evaluated
if the effect of any enclosing typeid expressions ([[expr.typeid]](expr.typeid "7.6.1.8Type identification"))
were ignored[.](#splice-2.1.sentence-1)
- [(2.2)](#splice-2.2)
Otherwise, if S is a function F,
the expression denotes an overload set containing all declarations of F that precede either the expression or
the point immediately following the [*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") of
the outermost class for which the expression is in a complete-class context;
overload resolution is performed ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"))[.](#splice-2.2.sentence-1)
- [(2.3)](#splice-2.3)
Otherwise, if S is an object or a non-static data member,
the expression is an lvalue designating S[.](#splice-2.3.sentence-1)
The expression has the same type as that of S, and
is a bit-field if and only if S is a bit-field[.](#splice-2.3.sentence-2)
[*Note [1](#splice-note-1)*:
The implicit transformation
whereby an [*id-expression*](#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denoting a non-static member
becomes a class member access ([[expr.prim.id]](#id "7.5.5Names"))
does not apply to a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")[.](#splice-2.3.sentence-3)
— *end note*]
- [(2.4)](#splice-2.4)
Otherwise, if S is a variable or a structured binding,S shall either have static or thread storage duration or
shall inhabit a scope enclosing the expression[.](#splice-2.4.sentence-1)
The expression is an lvalue referring to the object or function X associated with or referenced by S,
has the same type as that of S, and
is a bit-field if and only if X is a bit-field[.](#splice-2.4.sentence-2)
[*Note [2](#splice-note-2)*:
The type of a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") designating a variable or structured binding of reference type
will be adjusted to a non-reference type ([[expr.type]](expr.type "7.2.2Type"))[.](#splice-2.4.sentence-3)
— *end note*]
- [(2.5)](#splice-2.5)
Otherwise, if S is a value or an enumerator,
the expression is a prvalue that computes S and
whose type is the same as that of S[.](#splice-2.5.sentence-1)
- [(2.6)](#splice-2.6)
Otherwise, the expression is ill-formed[.](#splice-2.6.sentence-1)
[3](#splice-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3603)
For a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") of
the form template [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]"),
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") shall designate a function template T that is not a constructor template[.](#splice-3.sentence-1)
The expression denotes an overload set containing all declarations of T that precede either the expression or
the point immediately following the [*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") of
the outermost class for which the expression is in a complete-class context;
overload resolution is performed[.](#splice-3.sentence-2)
[*Note [3](#splice-note-3)*:
During overload resolution,
candidate function templates undergo template argument deduction and
the resulting specializations are considered as candidate functions[.](#splice-3.sentence-3)
— *end note*]
[4](#splice-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L3619)
For a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") of
the form template [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") of
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall designate a template T[.](#splice-4.sentence-1)
- [(4.1)](#splice-4.1)
If T is a function template,
the expression denotes an overload set containing all declarations of T that precede either the expression or
the point immediately following the [*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") of
the outermost class for which the expression is in a complete-class context;
overload resolution is performed ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"))[.](#splice-4.1.sentence-1)
- [(4.2)](#splice-4.2)
Otherwise, if T is a variable template,
let S be the specialization of T corresponding to
the template argument list of the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")[.](#splice-4.2.sentence-1)
The expression is an lvalue referring to
the object associated with S and has the same type as that of S[.](#splice-4.2.sentence-2)
- [(4.3)](#splice-4.3)
Otherwise, the expression is ill-formed[.](#splice-4.3.sentence-1)
[*Note [4](#splice-note-4)*:
Class members are accessible from any point
when designated by [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")*s* ([[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members"))[.](#splice-4.sentence-2)
A class member access expression ([[expr.ref]](expr.ref "7.6.1.5Class member access"))
whose right operand is a [*splice-expression*](#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") is ill-formed
if the left operand (considered as a pointer) cannot be implicitly converted
to a pointer to the designating class of the right operand[.](#splice-4.sentence-3)
— *end note*]