2216 lines
139 KiB
Markdown
2216 lines
139 KiB
Markdown
[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.1 Grammar [expr.prim.grammar]")
|
||
[*literal*](lex.literal.kinds#nt:literal "5.13.1 Kinds of literals [lex.literal.kinds]")
|
||
this
|
||
( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
[*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")
|
||
[*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")
|
||
[*fold-expression*](#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]")
|
||
[*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")
|
||
[*splice-expression*](#nt:splice-expression "7.5.9 Expression 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.1 Kinds of literals [lex.literal.kinds]") is determined based on its form as specified in [[lex.literal]](lex.literal "5.13 Literals")[.](#literal-1.sentence-1)
|
||
|
||
A [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") is an lvalue
|
||
designating a corresponding string literal object ([[lex.string]](lex.string "5.13.5 String literals")),
|
||
a [*user-defined-literal*](lex.ext#nt:user-defined-literal "5.13.9 User-defined literals [lex.ext]") has the same value category
|
||
as the corresponding operator call expression described in [[lex.ext]](lex.ext "5.13.9 User-defined literals"),
|
||
and any other [*literal*](lex.literal.kinds#nt:literal "5.13.1 Kinds 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.3 Non-static member functions")) is invoked or a non-static data member's
|
||
initializer ([[class.mem]](class.mem "11.4 Class 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.3 This [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.1 General [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.1 General"))
|
||
(including as the result of an implicit transformation ([[expr.prim.id.general]](#id.general "7.5.5.1 General"))
|
||
and including in the bodies of nested [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 General [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.1 General [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.1 General [dcl.decl.general]") and the end of the [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]"),[*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]"), or [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [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.1 General [dcl.decl.general]"),
|
||
the class being defined is not required to be complete
|
||
for purposes of [class member access](expr.ref "7.6.1.5 Class 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.1 General [class.mem.general]") declares a non-static data
|
||
member ([[class.mem]](class.mem "11.4 Class 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.4 Class 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.1 General [expr.prim.id.general]")
|
||
[*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")
|
||
[*qualified-id*](#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")
|
||
[*pack-index-expression*](#nt:pack-index-expression "7.5.5.4 Pack 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.1 General [expr.prim.id.general]") is a restricted form of a[*primary-expression*](#nt:primary-expression "7.5.1 Grammar [expr.prim.grammar]")[.](#id.general-1.sentence-1)
|
||
|
||
[*Note [1](#id.general-note-1)*:
|
||
|
||
An [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") can appear after[. and -> operators](expr.ref "7.6.1.5 Class 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.1 General [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.3 This")) 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.1 General [expr.prim.id.general]") of
|
||
a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), and
|
||
|
||
- [(2.3)](#id.general-2.3)
|
||
|
||
E is not the [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of
|
||
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The reflection operator")), and
|
||
|
||
- [(2.4)](#id.general-2.4)
|
||
|
||
if E is a [*qualified-id*](#nt:qualified-id "7.5.5.3 Qualified 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.2 Unary operators")),
|
||
|
||
the [*id-expression*](#nt:id-expression "7.5.5.1 General [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.1 General [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.2 Dependent 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.1 General [expr.prim.id.general]") E denotes
|
||
a member M of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous 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.5 Class 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.1 General [expr.prim.id.general]") or [*splice-expression*](#nt:splice-expression "7.5.9 Expression 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.2 Unary operators")), or
|
||
|
||
- [(4.3)](#id.general-4.3)
|
||
|
||
if that [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or [*splice-expression*](#nt:splice-expression "7.5.9 Expression 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.1 General [expr.prim.id.general]") that denotes an overload set,
|
||
overload resolution is performed
|
||
to select a unique function ([[over.match]](over.match "12.2 Overload resolution"), [[over.over]](over.over "12.3 Address 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.1 Preamble [temp.pre]") whose [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained 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.3 Context 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.2 Unqualified names [expr.prim.id.unqual]")
|
||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||
[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")
|
||
[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]")
|
||
[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]")
|
||
~ [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||
~ [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||
[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")
|
||
|
||
[1](#id.unqual-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L1521)
|
||
|
||
An [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is only
|
||
an [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") if it has
|
||
been suitably declared ([[dcl]](dcl "9 Declarations"))
|
||
or if it appears as part of a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#id.unqual-1.sentence-1)
|
||
|
||
[*Note [1](#id.unqual-note-1)*:
|
||
|
||
For [*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")*s*, see [[over.oper]](over.oper "12.4 Overloaded operators"); for[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]")*s*, see [[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions"); for[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]")*s*, see [[over.literal]](over.literal "12.6 User-defined literals"); for[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s*, see [[temp.names]](temp.names "13.3 Names of template specializations")[.](#id.unqual-1.sentence-2)
|
||
|
||
A [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") prefixed by ~ denotes the destructor of the type so named;
|
||
see [[expr.prim.id.dtor]](#id.dtor "7.5.5.5 Destruction")[.](#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.2 Unqualified names [expr.prim.id.unqual]") of an [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") U is
|
||
|
||
- [(2.1)](#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.3 Names of template specializations [temp.names]") or [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") of U, if any[.](#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.3 Qualified names"), [[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple type specifiers"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"), [[dcl.mptr]](dcl.mptr "9.3.4.4 Pointers to members"), [[namespace.udecl]](namespace.udecl "9.10 The using declaration"), [[temp.param]](temp.param "13.2 Template parameters"), [[temp.names]](temp.names "13.3 Names of template specializations"), [[temp.res]](temp.res "13.8 Name resolution"))[.](#id.unqual-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
The [*terminal name*](#def:name,terminal "7.5.5.2 Unqualified names [expr.prim.id.unqual]") of a construct is
|
||
the component name of that construct that appears lexically last[.](#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.2 Unqualified names [expr.prim.id.unqual]") ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3 Unqualified 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.2 Unqualified names [expr.prim.id.unqual]") appears in a [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 Preamble"))
|
||
or a variable declared by an [*init-capture*](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](#lambda.capture "7.5.6.3 Captures")),
|
||
|
||
- [(4.3)](#id.unqual-4.3)
|
||
|
||
naming the entity within the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of
|
||
the innermost enclosing [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") of P,
|
||
but not in an unevaluated operand, would refer to an entity captured by copy
|
||
in some intervening [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.6 Functions [dcl.fct]"),
|
||
of the innermost such [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") E,
|
||
|
||
then
|
||
the type of the expression is
|
||
the type of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))
|
||
naming the non-static data member
|
||
that would be declared for such a capture
|
||
in the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the function call operator of E[.](#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.2 Unqualified names [expr.prim.id.unqual]") names a coroutine parameter,
|
||
the type of the expression is
|
||
that of the copy of the parameter ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions")),
|
||
and the result is that copy[.](#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.2 Unqualified names [expr.prim.id.unqual]") names a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object"))
|
||
attached to a function *f* with return type U,
|
||
|
||
- [(6.1)](#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.2 Unqualified names [expr.prim.id.unqual]") appears in the predicate of a contract assertion C ([[basic.contract]](basic.contract "6.11 Contract assertions"))
|
||
and the entity is
|
||
|
||
- [(7.1)](#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.2 Template 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.2 Type") 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.7 Structured binding declarations")),
|
||
result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")),
|
||
data member, or
|
||
template parameter object;
|
||
and a prvalue otherwise ([[basic.lval]](basic.lval "7.2.1 Value category"));
|
||
it is a bit-field if the identifier designates a bit-field[.](#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.1 General [expr.prim.id.general]") E appears in the predicate of
|
||
a function contract assertion attached to a function *f* and denotes
|
||
a function parameter of *f* and the implementation introduces any temporary objects
|
||
to hold the value of that parameter as specified in [[class.temporary]](class.temporary "6.8.7 Temporary objects"),
|
||
|
||
- [(13.1)](#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.1 General [expr.prim.id.general]") E names a result binding
|
||
in a postcondition assertion
|
||
and the implementation introduces any temporary objects
|
||
to hold the result object as specified in [[class.temporary]](class.temporary "6.8.7 Temporary objects"),
|
||
and the postcondition assertion
|
||
is sequenced before the initialization of the result object ([[expr.call]](expr.call "7.6.1.3 Function call")),E refers to the most recently initialized such temporary object[.](#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.2 Unqualified names [expr.prim.id.unqual]") is
|
||
a variable with automatic storage duration
|
||
that is either a non-volatile object or
|
||
an rvalue reference to a non-volatile object type[.](#id.unqual-15.sentence-1)
|
||
|
||
An [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") or[*splice-expression*](#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") ([[expr.prim.splice]](#splice "7.5.9 Expression splicing"))
|
||
is [*move-eligible*](#def:move-eligible "7.5.5.2 Unqualified names [expr.prim.id.unqual]") if
|
||
|
||
- [(15.1)](#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.4 The return statement")) orco_return ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5 The co_return statement")) statement or
|
||
of a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]") ([[expr.throw]](expr.throw "7.6.18 Throwing an exception")), and
|
||
|
||
- [(15.3)](#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.18 Throwing an exception [expr.throw]"),
|
||
is not the block scope of
|
||
a [*try-block*](except.pre#nt:try-block "14.1 Preamble [except.pre]") or [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]")[.](#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.3 Qualified names [expr.prim.id.qual]")
|
||
[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")
|
||
|
||
[nested-name-specifier:](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")
|
||
::
|
||
[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") ::
|
||
[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") ::
|
||
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ::
|
||
[*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ::
|
||
[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ::
|
||
[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") ::
|
||
|
||
[splice-scope-specifier:](#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")
|
||
[*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")
|
||
templateopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") are those of
|
||
its [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and [*unqualified-id*](#nt:unqualified-id "7.5.5.2 Unqualified 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.3 Qualified names [expr.prim.id.qual]") are
|
||
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (if any) and those of its[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]"),[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]"), and/or[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified 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.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Qualified 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.6 Splice specifiers [basic.splice]") :: when the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Qualified 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.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") is [*declarative*](#def:declarative "7.5.5.3 Qualified 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.1 Preamble [class.pre]"),
|
||
|
||
- [(3.2)](#id.qual-3.2)
|
||
|
||
an [*enum-head-name*](dcl.enum#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]"),
|
||
|
||
- [(3.3)](#id.qual-3.3)
|
||
|
||
a [*qualified-id*](#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") that is the [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"), or
|
||
|
||
- [(3.4)](#id.qual-3.4)
|
||
|
||
a declarative [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#id.qual-3.sentence-1)
|
||
|
||
A declarative [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") shall not have a [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") or
|
||
a [*splice-scope-specifier*](#nt:splice-scope-specifier "7.5.5.3 Qualified 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.3 Qualified 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.3 Qualified 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.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") with a [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple 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.3 Simple 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.3 Qualified names [expr.prim.id.qual]") of
|
||
the form [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") ::,
|
||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") designates the same entity
|
||
as the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") of
|
||
the formtemplateopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") ::,
|
||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of
|
||
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.6 Splice 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.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") N is declarative and
|
||
has a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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.4 Template arguments")) of
|
||
the corresponding [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") H ([[temp.mem]](temp.mem "13.7.3 Member templates")),N designates the primary template of T;H shall be equivalent to
|
||
the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of T ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.6 Partial specialization")) of T whose template argument list is equivalent to A ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.3 Qualified names [expr.prim.id.qual]") designates
|
||
the entity denotes by its[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]"),[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"), or[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#id.qual-4.6.sentence-1)
|
||
If the [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") shall not be of the form[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt ~[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") nor of the form[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") :: ~ [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple 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.3 Qualified names [expr.prim.id.qual]") Q is
|
||
the entity it denotes ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified 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.11 Contract 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 Tâ, 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.7 Structured 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.4 Pack indexing expression [expr.prim.pack.index]")
|
||
[*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") ... [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.1 General [expr.prim.id.general]") P in a [*pack-index-expression*](#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]") shall be an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.7 Constant expressions [expr.const]") shall be
|
||
a converted constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) of type std::size_t whose value V, termed the index,
|
||
is such that 0â¤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.4 Pack indexing expression [expr.prim.pack.index]") is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.4 Pack 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.1 General [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.7 Destructors")),
|
||
otherwise the [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is said
|
||
to name a [*pseudo-destructor*](#def:pseudo-destructor "7.5.5.5 Destruction [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.1 General [expr.prim.id.general]") names a pseudo-destructor,T shall be a scalar type and
|
||
the [*id-expression*](#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") shall appear
|
||
as the right operand of a class member access ([[expr.ref]](expr.ref "7.6.1.5 Class member access")) that forms
|
||
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") of a function call ([[expr.call]](expr.call "7.6.1.3 Function 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.3 Function call"), [[basic.life]](basic.life "6.8.4 Lifetime"))[.](#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.9 User-defined literals [lex.ext]") ([[lex.ext]](lex.ext "5.13.9 User-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.1 General [expr.prim.lambda.general]")
|
||
[*lambda-introducer*](#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")
|
||
[*lambda-introducer*](#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]") < [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") > [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||
[*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")
|
||
|
||
[lambda-introducer:](#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]")
|
||
[ [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")opt ]
|
||
|
||
[lambda-declarator:](#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]")
|
||
[*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1 General [expr.prim.lambda.general]") [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")opt
|
||
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||
[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1 General [expr.prim.lambda.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")opt [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||
|
||
[lambda-specifier:](#nt:lambda-specifier "7.5.6.1 General [expr.prim.lambda.general]")
|
||
consteval
|
||
constexpr
|
||
mutable
|
||
static
|
||
|
||
[lambda-specifier-seq:](#nt:lambda-specifier-seq "7.5.6.1 General [expr.prim.lambda.general]")
|
||
[*lambda-specifier*](#nt:lambda-specifier "7.5.6.1 General [expr.prim.lambda.general]") [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1 General [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.1 General [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.1 General [expr.prim.lambda.general]") is a prvalue
|
||
whose result object is called the [*closure object*](#def:closure_object "7.5.6.1 General [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.10 Function 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.1 Preamble [temp.pre]") can end in
|
||
an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||
which collides with
|
||
the [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 Attribute syntax and semantics [dcl.attr.grammar]") in [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 General [expr.prim.lambda.general]") shall contain at most one of each [*lambda-specifier*](#nt:lambda-specifier "7.5.6.1 General [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.1 General [expr.prim.lambda.general]") contains
|
||
an explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||
then no [*lambda-specifier*](#nt:lambda-specifier "7.5.6.1 General [expr.prim.lambda.general]") in the [*lambda-specifier-seq*](#nt:lambda-specifier-seq "7.5.6.1 General [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.1 General [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.1 General [expr.prim.lambda.general]") contains static,
|
||
there shall be no [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [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.1 Preamble [temp.pre]") is described in [[dcl.decl]](dcl.decl "9.3 Declarators")[.](#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.1 General [expr.prim.lambda.general]")'s [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of
|
||
the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")'s [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]"), if any,
|
||
or empty otherwise[.](#lambda.general-5.sentence-1)
|
||
|
||
If the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") does not include a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [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.7 Placeholder 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.1 General [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.1 General [expr.prim.lambda.general]") if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") has any generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")), or
|
||
if the lambda has a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [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.1 General [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.2 Closure 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.4 Compound 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.1 General [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.4 Argument-dependent name lookup"))[.](#lambda.closure-3.sentence-2)
|
||
|
||
The parameter
|
||
types of a [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [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.2 Aggregates"));
|
||
it is a structural type ([[temp.param]](temp.param#term.structural.type "13.2 Template parameters")) if and only if
|
||
the lambda has no [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [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.2 Properties of classes")),
|
||
|
||
- [(4.3)](#lambda.closure-4.3)
|
||
|
||
whether the closure type is trivially relocatable ([[class.prop]](class.prop "11.2 Properties of classes")),
|
||
|
||
- [(4.4)](#lambda.closure-4.4)
|
||
|
||
whether the closure type is replaceable ([[class.prop]](class.prop "11.2 Properties of classes")), or
|
||
|
||
- [(4.5)](#lambda.closure-4.5)
|
||
|
||
whether the closure type is a standard-layout class ([[class.prop]](class.prop "11.2 Properties 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.1 General [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.4 Function call"))
|
||
whose parameters and return type
|
||
are those of the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") and [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") respectively, and whose[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of
|
||
the specified [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [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.1 Preamble [temp.pre]") of the function call operator template
|
||
is the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") immediately following< [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") >, if any[.](#lambda.closure-5.sentence-3)
|
||
|
||
The trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of the function call operator
|
||
or operator template is the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [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.6 Functions"))[.](#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.3 Captures [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.2 Static member functions"))
|
||
if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [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.3 Non-static member functions"))
|
||
that is declaredconst ([[class.mfct.non.static]](class.mfct.non.static "11.4.3 Non-static member functions")) if and only if the[*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")'s [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is not
|
||
followed by mutable and
|
||
the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [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.5 Exception specifications [except.spec]") or [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||
specified on a [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [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.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") preceding a [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [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.1 General [expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") is followed by constexpr or consteval, or
|
||
it is constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))[.](#lambda.closure-7.sentence-7)
|
||
|
||
It is an immediate function ([[dcl.constexpr]](dcl.constexpr "9.2.6 The constexpr and consteval specifiers"))
|
||
if the corresponding [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")'s[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [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.3 Constrained declarations"))
|
||
by a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||
a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")),
|
||
or a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#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.2 Template parameters [temp.param]").// T1 and T2 are constrained by a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"), and// T2 and the type of a4 are constrained by a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.1 General [expr.prim.lambda.general]") L occur within the function contract assertions ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||
of the call operator or operator template of L or within [*assertion-statement*](stmt.contract.assert#nt:assertion-statement "8.9 Assertion statement [stmt.contract.assert]")*s* ([[stmt.contract.assert]](stmt.contract.assert "8.9 Assertion 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.1 General [expr.prim.lambda.general]") with no[*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") and no explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))
|
||
whose constraints (if any) are satisfied
|
||
has a conversion function to pointer to
|
||
function with C++ language [linkage](dcl.link "9.12 Linkage 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.3 Captures [expr.prim.lambda.capture]") and no explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||
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.6 Decltype 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.1 General [dcl.decl.general]") or
|
||
the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [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.5 Exception 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.1 General [expr.prim.lambda.general]")'s [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") yields
|
||
the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") ([[dcl.fct.def]](dcl.fct.def "9.6 Function 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.4 Compound statement or block [stmt.block]") is
|
||
that of a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||
a variable __func__ is implicitly defined at the beginning of
|
||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),
|
||
with semantics as described in [[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")[.](#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.1 General [expr.prim.lambda.general]") has no
|
||
default constructor
|
||
if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") has a [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [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.3 Copy/move constructors"))[.](#lambda.closure-17.sentence-2)
|
||
|
||
It has a deleted copy assignment operator if the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") has a [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") and defaulted copy and move assignment
|
||
operators otherwise ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/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.1 General [expr.prim.lambda.general]") has an
|
||
implicitly-declared destructor ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#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.3 Explicit instantiation [temp.explicit]"),[explicitly specialized](temp.expl.spec "13.9.4 Explicit specialization [temp.expl.spec]"), or
|
||
named in a [friend declaration](class.friend "11.8.4 Friends [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.3 Captures [expr.prim.lambda.capture]")
|
||
[*capture-default*](#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*capture-list*](#nt:capture-list "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*capture-default*](#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]") , [*capture-list*](#nt:capture-list "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
|
||
[capture-default:](#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
&
|
||
=
|
||
|
||
[capture-list:](#nt:capture-list "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*capture*](#nt:capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*capture-list*](#nt:capture-list "7.5.6.3 Captures [expr.prim.lambda.capture]") , [*capture*](#nt:capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
|
||
[capture:](#nt:capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*init-capture*](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
|
||
[simple-capture:](#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ...opt
|
||
& [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ...opt
|
||
this
|
||
* this
|
||
|
||
[init-capture:](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")
|
||
...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")
|
||
& ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 General [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.3 Captures [expr.prim.lambda.capture]") includes a [*capture-default*](#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]") that
|
||
is &, no identifier in a [*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") of that[*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") shall be preceded
|
||
by &[.](#lambda.capture-2.sentence-1)
|
||
|
||
If a [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") includes a[*capture-default*](#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]") that is =, each[*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") of that [*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") shall
|
||
be of the form
|
||
â& [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.1 General [dcl.init.general]")*s* of [*init-capture*](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")*s*, an identifier orthis shall not appear more than once in a[*lambda-capture*](#nt:lambda-capture "7.5.6.3 Captures [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.1 General [expr.prim.lambda.general]") shall not have
|
||
a [*capture-default*](#nt:capture-default "7.5.6.3 Captures [expr.prim.lambda.capture]") or [*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") in its [*lambda-introducer*](#nt:lambda-introducer "7.5.6.1 General [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.3 Block 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.7 Class 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.10 Contract-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.11 Identifiers [lex.name]") in a [*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") shall denote a local entity ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3 Unqualified name lookup"), [[basic.pre]](basic.pre "6.1 Preamble"))[.](#lambda.capture-4.sentence-1)
|
||
|
||
The [*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [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.3 Captures [expr.prim.lambda.capture]") is said to be [*explicitly captured*](#def:explicitly_captured "7.5.6.3 Captures [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.11 Identifiers [lex.name]") in a [*capture*](#nt:capture "7.5.6.3 Captures [expr.prim.lambda.capture]") appears
|
||
as the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of a parameter of
|
||
the [*lambda-declarator*](#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]")'s [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") or as the name of a template parameter of
|
||
the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")'s [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [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.3 Captures [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.3 Captures [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.3 Captures [expr.prim.lambda.capture]") inhabits
|
||
the lambda scope ([[basic.scope.lambda]](basic.scope.lambda "6.4.5 Lambda scope"))
|
||
of the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")[.](#lambda.capture-6.sentence-1)
|
||
|
||
An [*init-capture*](#nt:init-capture "7.5.6.3 Captures [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.3 Captures [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.3 Captures [expr.prim.lambda.capture]") like
|
||
âx = std::move(x)â; the second âxâ 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.1 General [expr.prim.id.general]") that names a local entity
|
||
potentially references that entity;
|
||
an [*id-expression*](#nt:id-expression "7.5.5.1 General [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.2 Unary 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.1 General [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.1 General [expr.prim.lambda.general]") potentially references
|
||
the local entities named by its [*simple-capture*](#nt:simple-capture "7.5.6.3 Captures [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.3 One-definition rule")),
|
||
and the expression would be potentially evaluated
|
||
if the effect of any enclosing typeid expressions ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")) were ignored,
|
||
the entity is said to be [*implicitly captured*](#def:capture,implicit "7.5.6.3 Captures [expr.prim.lambda.capture]") by each intervening [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") with an associated[*capture-default*](#nt:capture-default "7.5.6.3 Captures [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.3 Captures [expr.prim.lambda.capture]") is =; see [[depr.capture.this]](depr.capture.this "D.3 Implicit 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.2 The 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.3 Captures [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.1 General [expr.prim.lambda.general]") is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) by
|
||
the [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 General [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.3 One-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.1 General [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.3 One-definition rule")),
|
||
a [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 General [expr.prim.lambda.general]") can still have an [*init-capture*](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") if
|
||
any full-expression in its [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") satisfies the constraints of an expression appearing in
|
||
a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default 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.3 Captures [expr.prim.lambda.capture]") if
|
||
|
||
- [(10.1)](#lambda.capture-10.1)
|
||
|
||
it is implicitly captured,
|
||
the [*capture-default*](#nt:capture-default "7.5.6.3 Captures [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.11 Identifiers [lex.name]") ...opt, or& ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 General [expr.prim.id.general]") within the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a[*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") that is an odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-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.1 General [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.1 General [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.3 Captures [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.1 General [expr.prim.id.general]") within
|
||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*lambda-expression*](#nt:lambda-expression "7.5.6.1 General [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.1 General [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.1 General [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.1 General [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.1 General [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.3 Captures [expr.prim.lambda.capture]")*s* are initialized as indicated by the corresponding[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 General [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.3 Captures [expr.prim.lambda.capture]") containing an ellipsis is a pack
|
||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#lambda.capture-17.sentence-1)
|
||
|
||
An [*init-capture*](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") containing an ellipsis is a pack
|
||
expansion that declares an[*init-capture*](#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.4 Variadic templates")) over a binary operator[.](#fold-1.sentence-1)
|
||
|
||
[fold-expression:](#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]")
|
||
( [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") [*fold-operator*](#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") ... )
|
||
( ... [*fold-operator*](#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") )
|
||
( [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") [*fold-operator*](#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") ... [*fold-operator*](#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") )
|
||
|
||
[fold-operator:](#nt:fold-operator "7.5.7 Fold 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.7 Fold expressions [expr.prim.fold]") is called a [*unary left fold*](#def:unary_left_fold "7.5.7 Fold 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.7 Fold expressions [expr.prim.fold]") is called a [*unary right fold*](#def:unary_right_fold "7.5.7 Fold 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.7 Fold expressions [expr.prim.fold]")[.](#fold-2.sentence-3)
|
||
|
||
In a unary fold,
|
||
the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") shall contain an unexpanded pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.7 Fold expressions [expr.prim.fold]")*s* is called a [*binary fold*](#def:binary_fold "7.5.7 Fold 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.7 Fold 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.7 Fold 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.7 Fold 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.1 General [expr.prim.req.general]") provides a concise way to express
|
||
requirements on template arguments
|
||
that can be checked by [name lookup](basic.lookup "6.5 Name lookup [basic.lookup]") or by checking properties of types and expressions[.](#req.general-1.sentence-1)
|
||
|
||
[requires-expression:](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")
|
||
requires [*requirement-parameter-list*](#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]")opt [*requirement-body*](#nt:requirement-body "7.5.8.1 General [expr.prim.req.general]")
|
||
|
||
[requirement-parameter-list:](#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]")
|
||
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") )
|
||
|
||
[requirement-body:](#nt:requirement-body "7.5.8.1 General [expr.prim.req.general]")
|
||
{ [*requirement-seq*](#nt:requirement-seq "7.5.8.1 General [expr.prim.req.general]") }
|
||
|
||
[requirement-seq:](#nt:requirement-seq "7.5.8.1 General [expr.prim.req.general]")
|
||
[*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]") [*requirement-seq*](#nt:requirement-seq "7.5.8.1 General [expr.prim.req.general]")opt
|
||
|
||
[requirement:](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")
|
||
[*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple requirements [expr.prim.req.simple]")
|
||
[*type-requirement*](#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]")
|
||
[*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")
|
||
[*nested-requirement*](#nt:nested-requirement "7.5.8.5 Nested 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.1 General [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.1 General [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.4 Concept convertible_to [concept.convertible]")<const typename T::type&>; };
|
||
|
||
A [*requires-expression*](#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") can also be used in a[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")) 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.1 Preamble [temp.pre]"), and the second
|
||
introduces the [*requires-expression*](#nt:requires-expression "7.5.8.1 General [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.1 General [expr.prim.req.general]") may introduce local parameters using a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")[.](#req.general-4.sentence-1)
|
||
|
||
A local parameter of a [*requires-expression*](#nt:requires-expression "7.5.8.1 General [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.6 Functions")[.](#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.1 General [expr.prim.req.general]")*s*[.](#req.general-4.sentence-4)
|
||
|
||
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of a[*requirement-parameter-list*](#nt:requirement-parameter-list "7.5.8.1 General [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.1 General [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.1 General [expr.prim.req.general]")*s* ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")) or
|
||
the violation of the semantic constraints of those [*requirement*](#nt:requirement "7.5.8.1 General [expr.prim.req.general]")*s*[.](#req.general-5.sentence-1)
|
||
|
||
In such cases, the [*requires-expression*](#nt:requires-expression "7.5.8.1 General [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.1 General [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.1 General [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.1 General [expr.prim.req.general]") contains invalid types or expressions in
|
||
its [*requirement*](#nt:requirement "7.5.8.1 General [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.1 General [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.2 Simple requirements [expr.prim.req.simple]")
|
||
[*expression*](expr.comma#nt:expression "7.6.20 Comma 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.2 Simple requirements [expr.prim.req.simple]") asserts
|
||
the validity of an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")[.](#req.simple-1.sentence-1)
|
||
|
||
The [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.1 General [expr.prim.req.general]") will evaluate to false if substitution of template arguments into the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.1 General [expr.prim.req.general]") that starts with a requires token
|
||
is never interpreted as a [*simple-requirement*](#nt:simple-requirement "7.5.8.2 Simple 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.2 Simple requirements [expr.prim.req.simple]") and a [*nested-requirement*](#nt:nested-requirement "7.5.8.5 Nested 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.3 Type requirements [expr.prim.req.type]")
|
||
typename [*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") ;
|
||
typename [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")
|
||
typename [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Type 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.3 Type requirements [expr.prim.req.type]") are those of its[*nested-name-specifier*](#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") (if any) and[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple 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.1 General [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.3 Names of template specializations")) [*template-id*](temp.names#nt:template-id "13.3 Names 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.3 Type 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.1 General"))[.](#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.4 Compound requirements [expr.prim.req.compound]")
|
||
{ [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") } noexceptopt [*return-type-requirement*](#nt:return-type-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")opt ;
|
||
|
||
[return-type-requirement:](#nt:return-type-requirement "7.5.8.4 Compound requirements [expr.prim.req.compound]")
|
||
-> [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.4 Compound requirements [expr.prim.req.compound]") asserts properties
|
||
of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") E[.](#req.compound-1.sentence-1)
|
||
|
||
The [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.20 Comma 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.5 Exception 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.4 Compound 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.4 Compound 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.2 Template parameters"))
|
||
of the [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.4 Compound 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.2 Simple 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.2 Concept same_as [concept.same]")<typename T::inner>;};
|
||
|
||
The [*compound-requirement*](#nt:compound-requirement "7.5.8.4 Compound 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.2 Concept 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.4 Compound 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.5 Nested requirements [expr.prim.req.nested]")
|
||
requires [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained 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.5 Nested 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.3 Constrained declarations [temp.constr.decl]") shall be satisfied ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained 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.5 Nested requirements [expr.prim.req.nested]") does not result in substitution into the [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") other than as specified in [[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints")[.](#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.3 Atomic 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.9 Expression splicing [expr.prim.splice]")
|
||
[*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")
|
||
template [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")
|
||
template [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.6 Splice specifiers [basic.splice]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") immediately followed by :: or preceded by typename is never interpreted as part of a [*splice-expression*](#nt:splice-expression "7.5.9 Expression 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.9 Type splicing [dcl.type.splice]")constexpr auto h = ^^g;constexpr auto i = e<[:^^h:]>; // error: unparenthesized [*splice-expression*](#nt:splice-expression "7.5.9 Expression 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.9 Expression splicing [expr.prim.splice]") of the form [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]"),
|
||
let S be the construct designated by [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.1 Preamble")) 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.8 Type 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.1 Preamble [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.2 Overload resolution"), [[over.over]](over.over "12.3 Address 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.1 General [expr.prim.id.general]") denoting a non-static member
|
||
becomes a class member access ([[expr.prim.id]](#id "7.5.5 Names"))
|
||
does not apply to a [*splice-expression*](#nt:splice-expression "7.5.9 Expression 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.9 Expression 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.2 Type"))[.](#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.9 Expression splicing [expr.prim.splice]") of
|
||
the form template [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]"),
|
||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.1 Preamble [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.9 Expression splicing [expr.prim.splice]") of
|
||
the form template [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"),
|
||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of
|
||
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.1 Preamble [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.2 Overload resolution"), [[over.over]](over.over "12.3 Address 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.6 Splice 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.9 Expression splicing [expr.prim.splice]")*s* ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members"))[.](#splice-4.sentence-2)
|
||
|
||
A class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))
|
||
whose right operand is a [*splice-expression*](#nt:splice-expression "7.5.9 Expression 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*]
|