- tmp/tmplxu48114/{from.md → to.md} +104 -69
tmp/tmplxu48114/{from.md → to.md}
RENAMED
|
@@ -6,44 +6,40 @@ type*, whose properties are described below.
|
|
| 6 |
|
| 7 |
The closure type is declared in the smallest block scope, class scope,
|
| 8 |
or namespace scope that contains the corresponding *lambda-expression*.
|
| 9 |
|
| 10 |
[*Note 1*: This determines the set of namespaces and classes associated
|
| 11 |
-
with the closure type
|
| 12 |
-
|
| 13 |
classes. — *end note*]
|
| 14 |
|
| 15 |
-
The closure type is not an aggregate type
|
| 16 |
implementation may define the closure type differently from what is
|
| 17 |
described below provided this does not alter the observable behavior of
|
| 18 |
the program other than by changing:
|
| 19 |
|
| 20 |
- the size and/or alignment of the closure type,
|
| 21 |
-
- whether the closure type is trivially copyable
|
| 22 |
-
- whether the closure type is a standard-layout class
|
| 23 |
-
[[class]]), or
|
| 24 |
-
- whether the closure type is a POD class (Clause [[class]]).
|
| 25 |
|
| 26 |
An implementation shall not add members of rvalue reference type to the
|
| 27 |
closure type.
|
| 28 |
|
| 29 |
-
The closure type for a
|
| 30 |
-
|
|
|
|
| 31 |
return type are described by the *lambda-expression*’s
|
| 32 |
-
*parameter-declaration-clause* and *trailing-return-type* respectively
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
*parameter-declaration-clause* by replacing each occurrence of `auto` in
|
| 43 |
-
the *decl-specifier*s of the *parameter-declaration-clause* with the
|
| 44 |
-
name of the corresponding invented *template-parameter*.
|
| 45 |
|
| 46 |
[*Example 1*:
|
| 47 |
|
| 48 |
``` cpp
|
| 49 |
auto glambda = [](auto a, auto&& b) { return a < b; };
|
|
@@ -74,14 +70,17 @@ specified on a *lambda-expression* applies to the corresponding function
|
|
| 74 |
call operator or operator template. An *attribute-specifier-seq* in a
|
| 75 |
*lambda-declarator* appertains to the type of the corresponding function
|
| 76 |
call operator or operator template. The function call operator or any
|
| 77 |
given operator template specialization is a constexpr function if either
|
| 78 |
the corresponding *lambda-expression*'s *parameter-declaration-clause*
|
| 79 |
-
is followed by `constexpr`, or it satisfies the
|
| 80 |
-
constexpr function
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
[*Note
|
| 83 |
the context in which the *lambda-expression* appears. — *end note*]
|
| 84 |
|
| 85 |
[*Example 2*:
|
| 86 |
|
| 87 |
``` cpp
|
|
@@ -90,11 +89,11 @@ static_assert(ID(3) == 3); // OK
|
|
| 90 |
|
| 91 |
struct NonLiteral {
|
| 92 |
NonLiteral(int n) : n(n) { }
|
| 93 |
int n;
|
| 94 |
};
|
| 95 |
-
static_assert(ID(NonLiteral{3}).n == 3);
|
| 96 |
```
|
| 97 |
|
| 98 |
— *end example*]
|
| 99 |
|
| 100 |
[*Example 3*:
|
|
@@ -118,35 +117,65 @@ static_assert(add(one)(zero)() == one()); // OK
|
|
| 118 |
// Since two below is not declared constexpr, an evaluation of its constexpr member function call operator
|
| 119 |
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
|
| 120 |
// in a constant expression.
|
| 121 |
auto two = monoid(2);
|
| 122 |
assert(two() == 2); // OK, not a constant expression.
|
| 123 |
-
static_assert(add(one)(one)() == two());
|
| 124 |
static_assert(add(one)(one)() == monoid(2)()); // OK
|
| 125 |
```
|
| 126 |
|
| 127 |
— *end example*]
|
| 128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
The closure type for a non-generic *lambda-expression* with no
|
| 130 |
-
*lambda-capture*
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
parameter types, as the function call operator template. The return type
|
| 143 |
-
of the pointer to function shall behave as if it were a
|
| 144 |
-
*decltype-specifier* denoting the return type of the corresponding
|
| 145 |
-
function call operator template specialization.
|
| 146 |
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
If the generic lambda has no *trailing-return-type* or the
|
| 150 |
*trailing-return-type* contains a placeholder type, return type
|
| 151 |
deduction of the corresponding function call operator template
|
| 152 |
specialization has to be done. The corresponding specialization is that
|
|
@@ -178,11 +207,11 @@ struct Closure {
|
|
| 178 |
};
|
| 179 |
```
|
| 180 |
|
| 181 |
— *end note*]
|
| 182 |
|
| 183 |
-
[*Example
|
| 184 |
|
| 185 |
``` cpp
|
| 186 |
void f1(int (*)(int)) { }
|
| 187 |
void f2(char (*)(int)) { }
|
| 188 |
|
|
@@ -203,19 +232,22 @@ int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
|
|
| 203 |
— *end example*]
|
| 204 |
|
| 205 |
The value returned by any given specialization of this conversion
|
| 206 |
function template is the address of a function `F` that, when invoked,
|
| 207 |
has the same effect as invoking the generic lambda’s corresponding
|
| 208 |
-
function call operator template specialization
|
| 209 |
-
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
-
[*Note
|
| 212 |
generic lambda’s body. The instantiated generic lambda’s return type and
|
| 213 |
-
parameter types
|
| 214 |
-
pointer to function. — *end note*]
|
| 215 |
|
| 216 |
-
[*Example
|
| 217 |
|
| 218 |
``` cpp
|
| 219 |
auto GL = [](auto a) { std::cout << a; return a; };
|
| 220 |
int (*GL_int)(int) = GL; // OK: through conversion function template
|
| 221 |
GL_int(3); // OK: same as GL(3)
|
|
@@ -223,37 +255,36 @@ GL_int(3); // OK: same as GL(3)
|
|
| 223 |
|
| 224 |
— *end example*]
|
| 225 |
|
| 226 |
The conversion function or conversion function template is public,
|
| 227 |
constexpr, non-virtual, non-explicit, const, and has a non-throwing
|
| 228 |
-
exception specification
|
| 229 |
|
| 230 |
-
[*Example
|
| 231 |
|
| 232 |
``` cpp
|
| 233 |
auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
|
| 234 |
auto C = [](auto a) { return a; };
|
| 235 |
|
| 236 |
static_assert(Fwd(C,3) == 3); // OK
|
| 237 |
|
| 238 |
// No specialization of the function call operator template can be constexpr (due to the local static).
|
| 239 |
auto NC = [](auto a) { static int s; return a; };
|
| 240 |
-
static_assert(Fwd(NC,3) == 3);
|
| 241 |
```
|
| 242 |
|
| 243 |
— *end example*]
|
| 244 |
|
| 245 |
The *lambda-expression*’s *compound-statement* yields the
|
| 246 |
-
*function-body*
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
*lambda-expression*.
|
| 253 |
|
| 254 |
-
[*Example
|
| 255 |
|
| 256 |
``` cpp
|
| 257 |
struct S1 {
|
| 258 |
int x, y;
|
| 259 |
int operator()(int);
|
|
@@ -271,18 +302,22 @@ struct S1 {
|
|
| 271 |
Further, a variable `__func__` is implicitly defined at the beginning of
|
| 272 |
the *compound-statement* of the *lambda-expression*, with semantics as
|
| 273 |
described in [[dcl.fct.def.general]].
|
| 274 |
|
| 275 |
The closure type associated with a *lambda-expression* has no default
|
| 276 |
-
constructor
|
| 277 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
|
| 279 |
-
[*Note
|
| 280 |
usual, and might therefore be defined as deleted. — *end note*]
|
| 281 |
|
| 282 |
The closure type associated with a *lambda-expression* has an
|
| 283 |
-
implicitly-declared destructor
|
| 284 |
|
| 285 |
-
A member of a closure type shall not be explicitly instantiated
|
| 286 |
-
[[temp.explicit]]
|
| 287 |
-
|
| 288 |
|
|
|
|
| 6 |
|
| 7 |
The closure type is declared in the smallest block scope, class scope,
|
| 8 |
or namespace scope that contains the corresponding *lambda-expression*.
|
| 9 |
|
| 10 |
[*Note 1*: This determines the set of namespaces and classes associated
|
| 11 |
+
with the closure type [[basic.lookup.argdep]]. The parameter types of a
|
| 12 |
+
*lambda-declarator* do not affect these associated namespaces and
|
| 13 |
classes. — *end note*]
|
| 14 |
|
| 15 |
+
The closure type is not an aggregate type [[dcl.init.aggr]]. An
|
| 16 |
implementation may define the closure type differently from what is
|
| 17 |
described below provided this does not alter the observable behavior of
|
| 18 |
the program other than by changing:
|
| 19 |
|
| 20 |
- the size and/or alignment of the closure type,
|
| 21 |
+
- whether the closure type is trivially copyable [[class.prop]], or
|
| 22 |
+
- whether the closure type is a standard-layout class [[class.prop]].
|
|
|
|
|
|
|
| 23 |
|
| 24 |
An implementation shall not add members of rvalue reference type to the
|
| 25 |
closure type.
|
| 26 |
|
| 27 |
+
The closure type for a *lambda-expression* has a public inline function
|
| 28 |
+
call operator (for a non-generic lambda) or function call operator
|
| 29 |
+
template (for a generic lambda) [[over.call]] whose parameters and
|
| 30 |
return type are described by the *lambda-expression*’s
|
| 31 |
+
*parameter-declaration-clause* and *trailing-return-type* respectively,
|
| 32 |
+
and whose *template-parameter-list* consists of the specified
|
| 33 |
+
*template-parameter-list*, if any. The *requires-clause* of the function
|
| 34 |
+
call operator template is the *requires-clause* immediately following
|
| 35 |
+
`<` *template-parameter-list* `>`, if any. The trailing
|
| 36 |
+
*requires-clause* of the function call operator or operator template is
|
| 37 |
+
the *requires-clause* of the *lambda-declarator*, if any.
|
| 38 |
+
|
| 39 |
+
[*Note 2*: The function call operator template for a generic lambda
|
| 40 |
+
might be an abbreviated function template [[dcl.fct]]. — *end note*]
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
[*Example 1*:
|
| 43 |
|
| 44 |
``` cpp
|
| 45 |
auto glambda = [](auto a, auto&& b) { return a < b; };
|
|
|
|
| 70 |
call operator or operator template. An *attribute-specifier-seq* in a
|
| 71 |
*lambda-declarator* appertains to the type of the corresponding function
|
| 72 |
call operator or operator template. The function call operator or any
|
| 73 |
given operator template specialization is a constexpr function if either
|
| 74 |
the corresponding *lambda-expression*'s *parameter-declaration-clause*
|
| 75 |
+
is followed by `constexpr` or `consteval`, or it satisfies the
|
| 76 |
+
requirements for a constexpr function [[dcl.constexpr]]. It is an
|
| 77 |
+
immediate function [[dcl.constexpr]] if the corresponding
|
| 78 |
+
*lambda-expression*'s *parameter-declaration-clause* is followed by
|
| 79 |
+
`consteval`.
|
| 80 |
|
| 81 |
+
[*Note 3*: Names referenced in the *lambda-declarator* are looked up in
|
| 82 |
the context in which the *lambda-expression* appears. — *end note*]
|
| 83 |
|
| 84 |
[*Example 2*:
|
| 85 |
|
| 86 |
``` cpp
|
|
|
|
| 89 |
|
| 90 |
struct NonLiteral {
|
| 91 |
NonLiteral(int n) : n(n) { }
|
| 92 |
int n;
|
| 93 |
};
|
| 94 |
+
static_assert(ID(NonLiteral{3}).n == 3); // error
|
| 95 |
```
|
| 96 |
|
| 97 |
— *end example*]
|
| 98 |
|
| 99 |
[*Example 3*:
|
|
|
|
| 117 |
// Since two below is not declared constexpr, an evaluation of its constexpr member function call operator
|
| 118 |
// cannot perform an lvalue-to-rvalue conversion on one of its subobjects (that represents its capture)
|
| 119 |
// in a constant expression.
|
| 120 |
auto two = monoid(2);
|
| 121 |
assert(two() == 2); // OK, not a constant expression.
|
| 122 |
+
static_assert(add(one)(one)() == two()); // error: two() is not a constant expression
|
| 123 |
static_assert(add(one)(one)() == monoid(2)()); // OK
|
| 124 |
```
|
| 125 |
|
| 126 |
— *end example*]
|
| 127 |
|
| 128 |
+
[*Note 4*:
|
| 129 |
+
|
| 130 |
+
The function call operator or operator template may be constrained
|
| 131 |
+
[[temp.constr.decl]] by a *type-constraint* [[temp.param]], a
|
| 132 |
+
*requires-clause* [[temp.pre]], or a trailing *requires-clause*
|
| 133 |
+
[[dcl.decl]].
|
| 134 |
+
|
| 135 |
+
[*Example 4*:
|
| 136 |
+
|
| 137 |
+
``` cpp
|
| 138 |
+
template <typename T> concept C1 = ...;
|
| 139 |
+
template <std::size_t N> concept C2 = ...;
|
| 140 |
+
template <typename A, typename B> concept C3 = ...;
|
| 141 |
+
|
| 142 |
+
auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)>
|
| 143 |
+
(T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3<decltype(a4), T2> {
|
| 144 |
+
// T2 is constrained by a type-constraint.
|
| 145 |
+
// T1 and T2 are constrained by a requires-clause, and
|
| 146 |
+
// T2 and the type of a4 are constrained by a trailing requires-clause.
|
| 147 |
+
};
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
— *end example*]
|
| 151 |
+
|
| 152 |
+
— *end note*]
|
| 153 |
+
|
| 154 |
The closure type for a non-generic *lambda-expression* with no
|
| 155 |
+
*lambda-capture* whose constraints (if any) are satisfied has a
|
| 156 |
+
conversion function to pointer to function with C++ language linkage
|
| 157 |
+
[[dcl.link]] having the same parameter and return types as the closure
|
| 158 |
+
type’s function call operator. The conversion is to “pointer to
|
| 159 |
+
`noexcept` function” if the function call operator has a non-throwing
|
| 160 |
+
exception specification. The value returned by this conversion function
|
| 161 |
+
is the address of a function `F` that, when invoked, has the same effect
|
| 162 |
+
as invoking the closure type’s function call operator on a
|
| 163 |
+
default-constructed instance of the closure type. `F` is a constexpr
|
| 164 |
+
function if the function call operator is a constexpr function and is an
|
| 165 |
+
immediate function if the function call operator is an immediate
|
| 166 |
+
function.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
+
For a generic lambda with no *lambda-capture*, the closure type has a
|
| 169 |
+
conversion function template to pointer to function. The conversion
|
| 170 |
+
function template has the same invented template parameter list, and the
|
| 171 |
+
pointer to function has the same parameter types, as the function call
|
| 172 |
+
operator template. The return type of the pointer to function shall
|
| 173 |
+
behave as if it were a *decltype-specifier* denoting the return type of
|
| 174 |
+
the corresponding function call operator template specialization.
|
| 175 |
+
|
| 176 |
+
[*Note 5*:
|
| 177 |
|
| 178 |
If the generic lambda has no *trailing-return-type* or the
|
| 179 |
*trailing-return-type* contains a placeholder type, return type
|
| 180 |
deduction of the corresponding function call operator template
|
| 181 |
specialization has to be done. The corresponding specialization is that
|
|
|
|
| 207 |
};
|
| 208 |
```
|
| 209 |
|
| 210 |
— *end note*]
|
| 211 |
|
| 212 |
+
[*Example 5*:
|
| 213 |
|
| 214 |
``` cpp
|
| 215 |
void f1(int (*)(int)) { }
|
| 216 |
void f2(char (*)(int)) { }
|
| 217 |
|
|
|
|
| 232 |
— *end example*]
|
| 233 |
|
| 234 |
The value returned by any given specialization of this conversion
|
| 235 |
function template is the address of a function `F` that, when invoked,
|
| 236 |
has the same effect as invoking the generic lambda’s corresponding
|
| 237 |
+
function call operator template specialization on a default-constructed
|
| 238 |
+
instance of the closure type. `F` is a constexpr function if the
|
| 239 |
+
corresponding specialization is a constexpr function and `F` is an
|
| 240 |
+
immediate function if the function call operator template specialization
|
| 241 |
+
is an immediate function.
|
| 242 |
|
| 243 |
+
[*Note 6*: This will result in the implicit instantiation of the
|
| 244 |
generic lambda’s body. The instantiated generic lambda’s return type and
|
| 245 |
+
parameter types are required to match the return type and parameter
|
| 246 |
+
types of the pointer to function. — *end note*]
|
| 247 |
|
| 248 |
+
[*Example 6*:
|
| 249 |
|
| 250 |
``` cpp
|
| 251 |
auto GL = [](auto a) { std::cout << a; return a; };
|
| 252 |
int (*GL_int)(int) = GL; // OK: through conversion function template
|
| 253 |
GL_int(3); // OK: same as GL(3)
|
|
|
|
| 255 |
|
| 256 |
— *end example*]
|
| 257 |
|
| 258 |
The conversion function or conversion function template is public,
|
| 259 |
constexpr, non-virtual, non-explicit, const, and has a non-throwing
|
| 260 |
+
exception specification [[except.spec]].
|
| 261 |
|
| 262 |
+
[*Example 7*:
|
| 263 |
|
| 264 |
``` cpp
|
| 265 |
auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
|
| 266 |
auto C = [](auto a) { return a; };
|
| 267 |
|
| 268 |
static_assert(Fwd(C,3) == 3); // OK
|
| 269 |
|
| 270 |
// No specialization of the function call operator template can be constexpr (due to the local static).
|
| 271 |
auto NC = [](auto a) { static int s; return a; };
|
| 272 |
+
static_assert(Fwd(NC,3) == 3); // error
|
| 273 |
```
|
| 274 |
|
| 275 |
— *end example*]
|
| 276 |
|
| 277 |
The *lambda-expression*’s *compound-statement* yields the
|
| 278 |
+
*function-body* [[dcl.fct.def]] of the function call operator, but for
|
| 279 |
+
purposes of name lookup [[basic.lookup]], determining the type and value
|
| 280 |
+
of `this` [[class.this]] and transforming *id-expression*s referring to
|
| 281 |
+
non-static class members into class member access expressions using
|
| 282 |
+
`(*this)` ([[class.mfct.non-static]]), the *compound-statement* is
|
| 283 |
+
considered in the context of the *lambda-expression*.
|
|
|
|
| 284 |
|
| 285 |
+
[*Example 8*:
|
| 286 |
|
| 287 |
``` cpp
|
| 288 |
struct S1 {
|
| 289 |
int x, y;
|
| 290 |
int operator()(int);
|
|
|
|
| 302 |
Further, a variable `__func__` is implicitly defined at the beginning of
|
| 303 |
the *compound-statement* of the *lambda-expression*, with semantics as
|
| 304 |
described in [[dcl.fct.def.general]].
|
| 305 |
|
| 306 |
The closure type associated with a *lambda-expression* has no default
|
| 307 |
+
constructor if the *lambda-expression* has a *lambda-capture* and a
|
| 308 |
+
defaulted default constructor otherwise. It has a defaulted copy
|
| 309 |
+
constructor and a defaulted move constructor [[class.copy.ctor]]. It has
|
| 310 |
+
a deleted copy assignment operator if the *lambda-expression* has a
|
| 311 |
+
*lambda-capture* and defaulted copy and move assignment operators
|
| 312 |
+
otherwise [[class.copy.assign]].
|
| 313 |
|
| 314 |
+
[*Note 7*: These special member functions are implicitly defined as
|
| 315 |
usual, and might therefore be defined as deleted. — *end note*]
|
| 316 |
|
| 317 |
The closure type associated with a *lambda-expression* has an
|
| 318 |
+
implicitly-declared destructor [[class.dtor]].
|
| 319 |
|
| 320 |
+
A member of a closure type shall not be explicitly instantiated
|
| 321 |
+
[[temp.explicit]], explicitly specialized [[temp.expl.spec]], or named
|
| 322 |
+
in a friend declaration [[class.friend]].
|
| 323 |
|