From Jason Turner

[exec.snd.expos]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp7g3_on21/{from.md → to.md} +627 -0
tmp/tmp7g3_on21/{from.md → to.md} RENAMED
@@ -0,0 +1,627 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Exposition-only entities <a id="exec.snd.expos">[[exec.snd.expos]]</a>
2
+
3
+ Subclause [[exec.snd]] makes use of the following exposition-only
4
+ entities.
5
+
6
+ For a queryable object `env`, `FWD-ENV(env)` is an expression whose type
7
+ satisfies `queryable` such that for a query object `q` and a pack of
8
+ subexpressions `as`, the expression `FWD-ENV(env).query(q, as...)` is
9
+ ill-formed if `forwarding_query(q)` is `false`; otherwise, it is
10
+ expression-equivalent to `env.query(q, as...)`. The type
11
+ `FWD-ENV-T(Env)` is `decltype(FWD-ENV(declval<Env>()))`.
12
+
13
+ For a query object `q` and a subexpression `v`, `MAKE-ENV(q, v)` is an
14
+ expression `env` whose type satisfies `queryable` such that the result
15
+ of `env.query(q)` has a value equal to `v` [[concepts.equality]]. Unless
16
+ otherwise stated, the object to which `env.query(q)` refers remains
17
+ valid while `env` remains valid.
18
+
19
+ For two queryable objects `env1` and `env2`, a query object `q`, and a
20
+ pack of subexpressions `as`, `JOIN-ENV(env1, env2)` is an expression
21
+ `env3` whose type satisfies `queryable` such that `env3.query(q, as...)`
22
+ is expression-equivalent to:
23
+
24
+ - `env1.query(q, as...)` if that expression is well-formed,
25
+ - otherwise, `env2.query(q, as...)` if that expression is well-formed,
26
+ - otherwise, `env3.query(q, as...)` is ill-formed.
27
+
28
+ The results of *`FWD-ENV`*, *`MAKE-ENV`*, and *`JOIN-ENV`* can be
29
+ context-dependent; i.e., they can evaluate to expressions with different
30
+ types and value categories in different contexts for the same arguments.
31
+
32
+ For a scheduler `sch`, `SCHED-ATTRS(sch)` is an expression `o1` whose
33
+ type satisfies `queryable` such that
34
+ `o1.query(get_completion_scheduler<Tag>)` is an expression with the same
35
+ type and value as `sch` where `Tag` is one of `set_value_t` or
36
+ `set_stopped_t`, and such that `o1.query(get_domain)` is
37
+ expression-equivalent to `sch.query(get_domain)`. `SCHED-ENV(sch)` is an
38
+ expression `o2` whose type satisfies `queryable` such that
39
+ `o2.query(get_scheduler)` is a prvalue with the same type and value as
40
+ `sch`, and such that `o2.query(get_domain)` is expression-equivalent to
41
+ `sch.query(get_domain)`.
42
+
43
+ For two subexpressions `rcvr` and `expr`, `SET-VALUE(rcvr, expr)` is
44
+ expression-equivalent to `(expr, set_value(std::move(rcvr)))` if the
45
+ type of `expr` is `void`; otherwise, `set_value(std::move(rcvr), expr)`.
46
+ `TRY-EVAL(rcvr, expr)` is equivalent to:
47
+
48
+ ``` cpp
49
+ try {
50
+ expr;
51
+ } catch(...) {
52
+ set_error(std::move(rcvr), current_exception());
53
+ }
54
+ ```
55
+
56
+ if `expr` is potentially-throwing; otherwise, `expr`.
57
+ `TRY-SET-VALUE(rcvr, expr)` is
58
+
59
+ ``` cpp
60
+ TRY-EVAL(rcvr, SET-VALUE(rcvr, expr))
61
+ ```
62
+
63
+ except that `rcvr` is evaluated only once.
64
+
65
+ ``` cpp
66
+ template<class Default = default_domain, class Sndr>
67
+ constexpr auto completion-domain(const Sndr& sndr) noexcept;
68
+ ```
69
+
70
+ *`COMPL-DOMAIN`*`(T)` is the type of the expression
71
+ `get_domain(get_completion_scheduler<T>(get_env(sndr)))`.
72
+
73
+ *Effects:* If all of the types *`COMPL-DOMAIN`*`(set_value_t)`,
74
+ *`COMPL-DOMAIN`*`(set_error_t)`, and *`COMPL-DOMAIN`*`(set_stopped_t)`
75
+ are ill-formed, `completion-domain<Default>(sndr)` is a
76
+ default-constructed prvalue of type `Default`. Otherwise, if they all
77
+ share a common type [[meta.trans.other]] (ignoring those types that are
78
+ ill-formed), then *`completion-domain`*`<Default>(sndr)` is a
79
+ default-constructed prvalue of that type. Otherwise,
80
+ *`completion-domain`*`<Default>(sndr)` is ill-formed.
81
+
82
+ ``` cpp
83
+ template<class Tag, class Env, class Default>
84
+ constexpr decltype(auto) query-with-default(
85
+ Tag, const Env& env, Default&& value) noexcept(see below);
86
+ ```
87
+
88
+ Let `e` be the expression `Tag()(env)` if that expression is
89
+ well-formed; otherwise, it is
90
+ `static_cast<Default>(std::forward<Default>(value))`.
91
+
92
+ *Returns:* `e`.
93
+
94
+ *Remarks:* The expression in the noexcept clause is `noexcept(e)`.
95
+
96
+ ``` cpp
97
+ template<class Sndr>
98
+ constexpr auto get-domain-early(const Sndr& sndr) noexcept;
99
+ ```
100
+
101
+ *Effects:* Equivalent to:
102
+
103
+ ``` cpp
104
+ return Domain();
105
+ ```
106
+
107
+ where `Domain` is the decayed type of the first of the following
108
+ expressions that is well-formed:
109
+
110
+ - `get_domain(get_env(sndr))`
111
+ - *`completion-domain`*`(sndr)`
112
+ - `default_domain()`
113
+
114
+ ``` cpp
115
+ template<class Sndr, class Env>
116
+ constexpr auto get-domain-late(const Sndr& sndr, const Env& env) noexcept;
117
+ ```
118
+
119
+ *Effects:* Equivalent to:
120
+
121
+ - If `sender-for<Sndr, continues_on_t>` is `true`, then
122
+ ``` cpp
123
+ return Domain();
124
+ ```
125
+
126
+ where `Domain` is the type of the following expression:
127
+ ``` cpp
128
+ [] {
129
+ auto [_, sch, _] = sndr;
130
+ return query-with-default(get_domain, sch, default_domain());
131
+ }();
132
+ ```
133
+
134
+ \[*Note 1*: The `continues_on` algorithm works in tandem with
135
+ `schedule_from`[[exec.schedule.from]] to give scheduler authors a
136
+ way to customize both how to transition onto (`continues_on`) and off
137
+ of (`schedule_from`) a given execution context. Thus, `continues_on`
138
+ ignores the domain of the predecessor and uses the domain of the
139
+ destination scheduler to select a customization, a property that is
140
+ unique to `continues_on`. That is why it is given special treatment
141
+ here. — *end note*]
142
+ - Otherwise,
143
+ ``` cpp
144
+ return Domain();
145
+ ```
146
+
147
+ where `Domain` is the first of the following expressions that is
148
+ well-formed and whose type is not `void`:
149
+ - `get_domain(get_env(sndr))`
150
+ - *`completion-domain`*`<void>(sndr)`
151
+ - `get_domain(env)`
152
+ - `get_domain(get_scheduler(env))`
153
+ - `default_domain()`
154
+
155
+ ``` cpp
156
+ template<callable Fun>
157
+ requires is_nothrow_move_constructible_v<Fun>
158
+ struct emplace-from {
159
+ Fun fun; // exposition only
160
+ using type = call-result-t<Fun>;
161
+
162
+ constexpr operator type() && noexcept(nothrow-callable<Fun>) {
163
+ return std::move(fun)();
164
+ }
165
+
166
+ constexpr type operator()() && noexcept(nothrow-callable<Fun>) {
167
+ return std::move(fun)();
168
+ }
169
+ };
170
+ ```
171
+
172
+ [*Note 2*: *`emplace-from`* is used to emplace non-movable types into
173
+ `tuple`, `optional`, `variant`, and similar types. — *end note*]
174
+
175
+ ``` cpp
176
+ struct on-stop-request {
177
+ inplace_stop_source& stop-src; // exposition only
178
+ void operator()() noexcept { stop-src.request_stop(); }
179
+ };
180
+ ```
181
+
182
+ ``` cpp
183
+ template<class T_0, class T_1, …, class T_n>
184
+ struct product-type { // exposition only
185
+ T_0 t_0; // exposition only
186
+ T_1 t_1; // exposition only
187
+
188
+ T_n t_n; // exposition only
189
+
190
+ template<size_t I, class Self>
191
+ constexpr decltype(auto) get(this Self&& self) noexcept; // exposition only
192
+
193
+ template<class Self, class Fn>
194
+ constexpr decltype(auto) apply(this Self&& self, Fn&& fn) // exposition only
195
+ noexcept(see below);
196
+ };
197
+ ```
198
+
199
+ [*Note 3*: *`product-type`* is presented here in pseudo-code form for
200
+ the sake of exposition. It can be approximated in standard C++ with a
201
+ tuple-like implementation that takes care to keep the type an aggregate
202
+ that can be used as the initializer of a structured binding
203
+ declaration. — *end note*]
204
+
205
+ [*Note 4*: An expression of type *`product-type`* is usable as the
206
+ initializer of a structured binding declaration
207
+ [[dcl.struct.bind]]. — *end note*]
208
+
209
+ ``` cpp
210
+ template<size_t I, class Self>
211
+ constexpr decltype(auto) get(this Self&& self) noexcept;
212
+ ```
213
+
214
+ *Effects:* Equivalent to:
215
+
216
+ ``` cpp
217
+ auto& [...ts] = self;
218
+ return std::forward_like<Self>(ts...[I]);
219
+ ```
220
+
221
+ ``` cpp
222
+ template<class Self, class Fn>
223
+ constexpr decltype(auto) apply(this Self&& self, Fn&& fn) noexcept(see below);
224
+ ```
225
+
226
+ *Constraints:* The expression in the `return` statement below is
227
+ well-formed.
228
+
229
+ *Effects:* Equivalent to:
230
+
231
+ ``` cpp
232
+ auto& [...ts] = self;
233
+ return std::forward<Fn>(fn)(std::forward_like<Self>(ts)...);
234
+ ```
235
+
236
+ *Remarks:* The expression in the `noexcept` clause is `true` if the
237
+ `return` statement above is not potentially throwing; otherwise,
238
+ `false`.
239
+
240
+ Let `valid-specialization` be the following concept:
241
+
242
+ ``` cpp
243
+ namespace std::execution {
244
+ template<template<class...> class T, class... Args>
245
+ concept valid-specialization = // exposition only
246
+ requires { typename T<Args...>; };
247
+ }
248
+ ```
249
+
250
+ ``` cpp
251
+ template<class Tag, class Data = see below, class... Child>
252
+ constexpr auto make-sender(Tag tag, Data&& data, Child&&... child);
253
+ ```
254
+
255
+ *Mandates:* The following expressions are `true`:
256
+
257
+ - `semiregular<Tag>`
258
+ - `movable-value<Data>`
259
+ - `(sender<Child> && ...)`
260
+ - `dependent_sender<Sndr> || sender_in<Sndr>`, where `Sndr` is
261
+ *`basic-sender`*`<Tag, Data,Child...>` as defined below. *Recommended
262
+ practice:* If evaluation of `sender_in<Sndr>` results in an uncaught
263
+ exception from the evaluation of `get_completion_signatures<Sndr>()`,
264
+ the implementation should include information about that exception in
265
+ the resulting diagnostic.
266
+
267
+ *Returns:* A prvalue of type
268
+ *`basic-sender`*`<Tag, decay_t<Data>, decay_t<Child>...>` that has been
269
+ direct-list-initialized with the forwarded arguments, where
270
+ *basic-sender* is the following exposition-only class template except as
271
+ noted below.
272
+
273
+ *Remarks:* The default template argument for the `Data` template
274
+ parameter denotes an unspecified empty trivially copyable class type
275
+ that models `semiregular`.
276
+
277
+ ``` cpp
278
+ namespace std::execution {
279
+ template<class Tag>
280
+ concept completion-tag = // exposition only
281
+ same_as<Tag, set_value_t> || same_as<Tag, set_error_t> || same_as<Tag, set_stopped_t>;
282
+
283
+ struct default-impls { // exposition only
284
+ static constexpr auto get-attrs = see belownc; // exposition only
285
+ static constexpr auto get-env = see belownc; // exposition only
286
+ static constexpr auto get-state = see belownc; // exposition only
287
+ static constexpr auto start = see belownc; // exposition only
288
+ static constexpr auto complete = see belownc; // exposition only
289
+
290
+ template<class Sndr, class... Env>
291
+ static consteval void check-types(); // exposition only
292
+ };
293
+
294
+ template<class Tag>
295
+ struct impls-for : default-impls {}; // exposition only
296
+
297
+ template<class Sndr, class Rcvr> // exposition only
298
+ using state-type = decay_t<call-result-t<
299
+ decltype(impls-for<tag_of_t<Sndr>>::get-state), Sndr, Rcvr&>>;
300
+
301
+ template<class Index, class Sndr, class Rcvr> // exposition only
302
+ using env-type = call-result-t<
303
+ decltype(impls-for<tag_of_t<Sndr>>::get-env), Index,
304
+ state-type<Sndr, Rcvr>&, const Rcvr&>;
305
+
306
+ template<class Sndr>
307
+ using data-type = decltype(declval<Sndr>().template get<1>()); // exposition only
308
+
309
+ template<class Sndr, size_t I = 0>
310
+ using child-type = decltype(declval<Sndr>().template get<I+2>()); // exposition only
311
+
312
+ template<class Sndr>
313
+ using indices-for = remove_reference_t<Sndr>::indices-for; // exposition only
314
+
315
+ template<class Sndr, class Rcvr>
316
+ struct basic-state { // exposition only
317
+ basic-state(Sndr&& sndr, Rcvr&& rcvr) noexcept(see below)
318
+ : rcvr(std::move(rcvr))
319
+ , state(impls-for<tag_of_t<Sndr>>::get-state(std::forward<Sndr>(sndr), rcvr)) { }
320
+
321
+ Rcvr rcvr; // exposition only
322
+ state-type<Sndr, Rcvr> state; // exposition only
323
+ };
324
+
325
+ template<class Sndr, class Rcvr, class Index>
326
+ requires valid-specialization<env-type, Index, Sndr, Rcvr>
327
+ struct basic-receiver { // exposition only
328
+ using receiver_concept = receiver_t;
329
+
330
+ using tag-t = tag_of_t<Sndr>; // exposition only
331
+ using state-t = state-type<Sndr, Rcvr>; // exposition only
332
+ static constexpr const auto& complete = impls-for<tag-t>::complete; // exposition only
333
+
334
+ template<class... Args>
335
+ requires callable<decltype(complete), Index, state-t&, Rcvr&, set_value_t, Args...>
336
+ void set_value(Args&&... args) && noexcept {
337
+ complete(Index(), op->state, op->rcvr, set_value_t(), std::forward<Args>(args)...);
338
+ }
339
+
340
+ template<class Error>
341
+ requires callable<decltype(complete), Index, state-t&, Rcvr&, set_error_t, Error>
342
+ void set_error(Error&& err) && noexcept {
343
+ complete(Index(), op->state, op->rcvr, set_error_t(), std::forward<Error>(err));
344
+ }
345
+
346
+ void set_stopped() && noexcept
347
+ requires callable<decltype(complete), Index, state-t&, Rcvr&, set_stopped_t> {
348
+ complete(Index(), op->state, op->rcvr, set_stopped_t());
349
+ }
350
+
351
+ auto get_env() const noexcept -> env-type<Index, Sndr, Rcvr> {
352
+ return impls-for<tag-t>::get-env(Index(), op->state, op->rcvr);
353
+ }
354
+
355
+ basic-state<Sndr, Rcvr>* op; // exposition only
356
+ };
357
+
358
+ constexpr auto connect-all = see belownc; // exposition only
359
+
360
+ template<class Sndr, class Rcvr>
361
+ using connect-all-result = call-result-t< // exposition only
362
+ decltype(connect-all), basic-state<Sndr, Rcvr>*, Sndr, indices-for<Sndr>>;
363
+
364
+ template<class Sndr, class Rcvr>
365
+ requires valid-specialization<state-type, Sndr, Rcvr> &&
366
+ valid-specialization<connect-all-result, Sndr, Rcvr>
367
+ struct basic-operation : basic-state<Sndr, Rcvr> { // exposition only
368
+ using operation_state_concept = operation_state_t;
369
+ using tag-t = tag_of_t<Sndr>; // exposition only
370
+
371
+ connect-all-result<Sndr, Rcvr> inner-ops; // exposition only
372
+
373
+ basic-operation(Sndr&& sndr, Rcvr&& rcvr) noexcept(see belownc) // exposition only
374
+ : basic-state<Sndr, Rcvr>(std::forward<Sndr>(sndr), std::move(rcvr)),
375
+ inner-ops(connect-all(this, std::forward<Sndr>(sndr), indices-for<Sndr>()))
376
+ {}
377
+
378
+ void start() & noexcept {
379
+ auto& [...ops] = inner-ops;
380
+ impls-for<tag-t>::start(this->state, this->rcvr, ops...);
381
+ }
382
+ };
383
+
384
+ template<class Tag, class Data, class... Child>
385
+ struct basic-sender : product-type<Tag, Data, Child...> { // exposition only
386
+ using sender_concept = sender_t;
387
+ using indices-for = index_sequence_for<Child...>; // exposition only
388
+
389
+ decltype(auto) get_env() const noexcept {
390
+ auto& [_, data, ...child] = *this;
391
+ return impls-for<Tag>::get-attrs(data, child...);
392
+ }
393
+
394
+ template<decays-to<basic-sender> Self, receiver Rcvr>
395
+ auto connect(this Self&& self, Rcvr rcvr) noexcept(see below)
396
+ -> basic-operation<Self, Rcvr> {
397
+ return {std::forward<Self>(self), std::move(rcvr)};
398
+ }
399
+
400
+ template<decays-to<basic-sender> Self, class... Env>
401
+ static constexpr auto get_completion_signatures();
402
+ };
403
+ }
404
+ ```
405
+
406
+ It is unspecified whether a specialization of *`basic-sender`* is an
407
+ aggregate.
408
+
409
+ An expression of type *`basic-sender`* is usable as the initializer of a
410
+ structured binding declaration [[dcl.struct.bind]].
411
+
412
+ The expression in the `noexcept` clause of the constructor of
413
+ *`basic-state`* is
414
+
415
+ ``` cpp
416
+ is_nothrow_move_constructible_v<Rcvr> &&
417
+ nothrow-callable<decltype(impls-for<tag_of_t<Sndr>>::get-state), Sndr, Rcvr&> &&
418
+ (same_as<state-type<Sndr, Rcvr>, get-state-result> ||
419
+ is_nothrow_constructible_v<state-type<Sndr, Rcvr>, get-state-result>)
420
+ ```
421
+
422
+ where *`get-state-result`* is
423
+
424
+ ``` cpp
425
+ call-result-t<decltype(impls-for<tag_of_t<Sndr>>::get-state), Sndr, Rcvr&>.
426
+ ```
427
+
428
+ The object *`connect-all`* is initialized with a callable object
429
+ equivalent to the following lambda:
430
+
431
+ ``` cpp
432
+ []<class Sndr, class Rcvr, size_t... Is>(
433
+ basic-state<Sndr, Rcvr>* op, Sndr&& sndr, index_sequence<Is...>) noexcept(see below)
434
+ -> decltype(auto) {
435
+ auto& [_, data, ...child] = sndr;
436
+ return product-type{connect(
437
+ std::forward_like<Sndr>(child),
438
+ basic-receiver<Sndr, Rcvr, integral_constant<size_t, Is>>{op})...};
439
+ }
440
+ ```
441
+
442
+ *Constraints:* The expression in the `return` statement is well-formed.
443
+
444
+ *Remarks:* The expression in the `noexcept` clause is `true` if the
445
+ `return` statement is not potentially throwing; otherwise, `false`.
446
+
447
+ The expression in the `noexcept` clause of the constructor of
448
+ *`basic-operation`* is:
449
+
450
+ ``` cpp
451
+ is_nothrow_constructible_v<basic-state<Self, Rcvr>, Self, Rcvr> &&
452
+ noexcept(connect-all(this, std::forward<Sndr>(sndr), indices-for<Sndr>()))
453
+ ```
454
+
455
+ The expression in the `noexcept` clause of the `connect` member function
456
+ of *`basic-sender`* is:
457
+
458
+ ``` cpp
459
+ is_nothrow_constructible_v<basic-operation<Self, Rcvr>, Self, Rcvr>
460
+ ```
461
+
462
+ The member `default-impls::get-attrs` is initialized with a callable
463
+ object equivalent to the following lambda:
464
+
465
+ ``` cpp
466
+ [](const auto&, const auto&... child) noexcept -> decltype(auto) {
467
+ if constexpr (sizeof...(child) == 1)
468
+ return (FWD-ENV(get_env(child)), ...);
469
+ else
470
+ return env<>();
471
+ }
472
+ ```
473
+
474
+ The member `default-impls::get-env` is initialized with a callable
475
+ object equivalent to the following lambda:
476
+
477
+ ``` cpp
478
+ [](auto, auto&, const auto& rcvr) noexcept -> decltype(auto) {
479
+ return FWD-ENV(get_env(rcvr));
480
+ }
481
+ ```
482
+
483
+ The member `default-impls::get-state` is initialized with a callable
484
+ object equivalent to the following lambda:
485
+
486
+ ``` cpp
487
+ []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept -> decltype(auto) {
488
+ auto& [_, data, ...child] = sndr;
489
+ return allocator-aware-forward(std::forward_like<Sndr>(data), rcvr);
490
+ }
491
+ ```
492
+
493
+ The member `default-impls::start` is initialized with a callable object
494
+ equivalent to the following lambda:
495
+
496
+ ``` cpp
497
+ [](auto&, auto&, auto&... ops) noexcept -> void {
498
+ (execution::start(ops), ...);
499
+ }
500
+ ```
501
+
502
+ The member `default-impls::complete` is initialized with a callable
503
+ object equivalent to the following lambda:
504
+
505
+ ``` cpp
506
+ []<class Index, class Rcvr, class Tag, class... Args>(
507
+ Index, auto& state, Rcvr& rcvr, Tag, Args&&... args) noexcept
508
+ -> void requires callable<Tag, Rcvr, Args...> {
509
+ static_assert(Index::value == 0);
510
+ Tag()(std::move(rcvr), std::forward<Args>(args)...);
511
+ }
512
+ ```
513
+
514
+ ``` cpp
515
+ template<class Sndr, class... Env>
516
+ static consteval void default-impls::check-types();
517
+ ```
518
+
519
+ Let `Is` be the pack of integral template arguments of the
520
+ `integer_sequence` specialization denoted by *`indices-for`*`<Sndr>`.
521
+
522
+ *Effects:* Equivalent to:
523
+
524
+ ``` cpp
525
+ (get_completion_signatures<child-type<Sndr, Is>, FWD-ENV-T(Env)...>(), ...);
526
+ ```
527
+
528
+ [*Note 1*:
529
+
530
+ For any types `T` and `S`, and pack `E`, let `e` be the expression
531
+ *`impls-for`*`<T>::`*`check-types`*`<S, E...>()`. Then exactly one of
532
+ the following is `true`:
533
+
534
+ - `e` is ill-formed, or
535
+ - the evaluation of `e` exits with an exception, or
536
+ - `e` is a core constant expression.
537
+
538
+ When `e` is a core constant expression, the pack `S, E...` uniquely
539
+ determines a set of completion signatures.
540
+
541
+ — *end note*]
542
+
543
+ ``` cpp
544
+ template<class Tag, class Data, class... Child>
545
+ template<class Sndr, class... Env>
546
+ constexpr auto basic-sender<Tag, Data, Child...>::get_completion_signatures();
547
+ ```
548
+
549
+ Let `Rcvr` be the type of a receiver whose environment has type `E`,
550
+ where `E` is the first type in the list `Env..., env<>`. Let
551
+ *`CHECK-TYPES`*`()` be the expression
552
+ *`impls-for`*`<Tag>::template `*`check-types`*`<Sndr, E>()`, and let
553
+ `CS` be a type determined as follows:
554
+
555
+ - If *`CHECK-TYPES`*`()` is a core constant expression, let `op` be an
556
+ lvalue subexpression whose type is `connect_result_t<Sndr, Rcvr>`.
557
+ Then `CS` is the specialization of `completion_signatures` the set of
558
+ whose template arguments correspond to the set of completion
559
+ operations that are potentially evaluated [[basic.def.odr]] as a
560
+ result of evaluating `op.start()`.
561
+ - Otherwise, `CS` is `completion_signatures<>`.
562
+
563
+ *Constraints:* *`CHECK-TYPES`*`()` is a well-formed expression.
564
+
565
+ *Effects:* Equivalent to:
566
+
567
+ ``` cpp
568
+ CHECK-TYPES();
569
+ return CS();
570
+ ```
571
+
572
+ ``` cpp
573
+ template<class... Fns>
574
+ struct overload-set : Fns... {
575
+ using Fns::operator()...;
576
+ };
577
+ ```
578
+
579
+ ``` cpp
580
+ struct not-a-sender {
581
+ using sender_concept = sender_t;
582
+
583
+ template<class Sndr>
584
+ static consteval auto get_completion_signatures() -> completion_signatures<> {
585
+ throw unspecified-exception();
586
+ }
587
+ };
588
+ ```
589
+
590
+ where `unspecified-exception` is a type derived from `exception`.
591
+
592
+ ``` cpp
593
+ constexpr void decay-copyable-result-datums(auto cs) {
594
+ cs.for-each([]<class Tag, class... Ts>(Tag(*)(Ts...)) {
595
+ if constexpr (!(is_constructible_v<decay_t<Ts>, Ts> &&...))
596
+ throw unspecified-exception();
597
+ });
598
+ }
599
+ ```
600
+
601
+ where `unspecified-exception` is a type derived from `exception`.
602
+
603
+ ``` cpp
604
+ template<class T, class Context>
605
+ decltype(auto) allocator-aware-forward(T&& obj, Context&& context); // exposition only
606
+ ```
607
+
608
+ *allocator-aware-forward* is an exposition-only function template used
609
+ to either create a new object of type `remove_cvref_t<T>` from `obj` or
610
+ forward `obj` depending on whether an allocator is available. If the
611
+ environment associated with `context` provides an allocator (i.e., the
612
+ expression `get_allocator(get_env(context))` is valid), let *alloc* be
613
+ the result of this expression and let `P` be `remove_cvref_t<T>`.
614
+
615
+ *Returns:*
616
+
617
+ - If *alloc* is not defined, returns `std::forward<T>(obj)`,
618
+ - otherwise if `P` is a specialization of *product-type*, returns an
619
+ object of type `P` whose elements are initialized using
620
+ ``` cpp
621
+ make_obj_using_allocator<decltype(e)>(std::forward_like<T>(e), alloc)
622
+ ```
623
+
624
+ where `e` is the corresponding element of `obj`,
625
+ - otherwise, returns
626
+ `make_obj_using_allocator<P>(std::forward<T>(obj), `*`alloc`*`)`.
627
+