Files
cppdraft_translate/cppdraft/exec/snd/expos.md
2025-10-25 03:02:53 +03:00

605 lines
30 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

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

[exec.snd.expos]
# 33 Execution control library [[exec]](./#exec)
## 33.9 Senders [[exec.snd]](exec.snd#expos)
### 33.9.2 Exposition-only entities [exec.snd.expos]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1373)
Subclause [[exec.snd]](exec.snd "33.9Senders") makes use of the following exposition-only entities[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1376)
For a queryable object env,*FWD-ENV*(env) is an expression
whose type satisfies [*queryable*](exec.queryable.concept#concept:queryable "33.2.2queryable concept[exec.queryable.concept]") such that for a query object q and
a pack of subexpressions as,
the expression *FWD-ENV*(env).query(q, as...) is ill-formed
if forwarding_query(q) is false;
otherwise, it is expression-equivalent to env.query(q, as...)[.](#2.sentence-1)
The type *FWD-ENV-T*(Env) isdecltype(*FWD-ENV*(declval<Env>()))[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1390)
For a query object q and a subexpression v,*MAKE-ENV*(q, v) is an expression env whose type satisfies [*queryable*](exec.queryable.concept#concept:queryable "33.2.2queryable concept[exec.queryable.concept]") such that the result of env.query(q) has
a value equal to v ([[concepts.equality]](concepts.equality "18.2Equality preservation"))[.](#3.sentence-1)
Unless otherwise stated,
the object to which env.query(q) refers remains valid
while env remains valid[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1400)
For two queryable objects env1 and env2,
a query object q, and
a pack of subexpressions as,*JOIN-ENV*(env1, env2) is an expression env3 whose type satisfies [*queryable*](exec.queryable.concept#concept:queryable "33.2.2queryable concept[exec.queryable.concept]") such that env3.query(q, as...) is expression-equivalent to:
- [(4.1)](#4.1)
env1.query(q, as...) if that expression is well-formed,
- [(4.2)](#4.2)
otherwise, env2.query(q, as...) if that expression is well-formed,
- [(4.3)](#4.3)
otherwise, env3.query(q, as...) is ill-formed[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1416)
The results of *FWD-ENV*, *MAKE-ENV*, and *JOIN-ENV* can be context-dependent;
i.e., they can evaluate to expressions
with different types and value categories
in different contexts for the same arguments[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1423)
For a scheduler sch,*SCHED-ATTRS*(sch) is an expression o1 whose type satisfies [*queryable*](exec.queryable.concept#concept:queryable "33.2.2queryable concept[exec.queryable.concept]") such that o1.query(get_completion_scheduler<Tag>) is
an expression with the same type and value as sch where Tag is one of set_value_t or set_stopped_t, and
such that o1.query(get_domain) is expression-equivalent tosch.query(get_domain)[.](#6.sentence-1)
*SCHED-ENV*(sch) is an expression o2 whose type satisfies [*queryable*](exec.queryable.concept#concept:queryable "33.2.2queryable concept[exec.queryable.concept]") such that o2.query(get_scheduler) is a prvalue
with the same type and value as sch, and
such that o2.query(get_domain) is expression-equivalent tosch.query(get_domain)[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1439)
For two subexpressions rcvr and expr,*SET-VALUE*(rcvr, expr) is expression-equivalent to(expr, set_value(std::move(rcvr))) if the type of expr is void;
otherwise, set_value(std::move(rcvr), expr)[.](#7.sentence-1)
*TRY-EVAL*(rcvr, expr) is equivalent to:try { expr;} catch(...) { set_error(std::move(rcvr), current_exception());} if expr is potentially-throwing; otherwise, expr[.](#7.sentence-2)
*TRY-SET-VALUE*(rcvr, expr) is*TRY-EVAL*(rcvr, *SET-VALUE*(rcvr, expr)) except that rcvr is evaluated only once[.](#7.sentence-3)
[🔗](#itemdecl:1)
`template<class Default = default_domain, class Sndr>
constexpr auto completion-domain(const Sndr& sndr) noexcept;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1466)
*COMPL-DOMAIN*(T) is the type of the expressionget_domain(get_completion_scheduler<T>(get_env(sndr)))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1470)
*Effects*: If all of the types*COMPL-DOMAIN*(set_value_t),*COMPL-DOMAIN*(set_error_t), and
*COMPL-DOMAIN*(set_stopped_t) are ill-formed,completion-domain<Default>(sndr) is
a default-constructed prvalue of type Default[.](#9.sentence-1)
Otherwise, if they all share a common type ([[meta.trans.other]](meta.trans.other "21.3.9.7Other transformations"))
(ignoring those types that are ill-formed),
then *completion-domain*<Default>(sndr) is
a default-constructed prvalue of that type[.](#9.sentence-2)
Otherwise, *completion-domain*<Default>(sndr) is ill-formed[.](#9.sentence-3)
[🔗](#itemdecl:2)
`template<class Tag, class Env, class Default>
constexpr decltype(auto) query-with-default(
Tag, const Env& env, Default&& value) noexcept(see below);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1492)
Let e be the expression Tag()(env) if that expression is well-formed;
otherwise, it is static_cast<Default>(std::forward<Default>(value))[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1497)
*Returns*: e[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1501)
*Remarks*: The expression in the noexcept clause is noexcept(e)[.](#12.sentence-1)
[🔗](#itemdecl:3)
`template<class Sndr>
constexpr auto get-domain-early(const Sndr& sndr) noexcept;
`
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1512)
*Effects*: Equivalent to:return Domain(); where Domain is
the decayed type of the first of the following expressions that is well-formed:
- [(13.1)](#13.1)
get_domain(get_env(sndr))
- [(13.2)](#13.2)
*completion-domain*(sndr)
- [(13.3)](#13.3)
default_domain()
[🔗](#itemdecl:4)
`template<class Sndr, class Env>
constexpr auto get-domain-late(const Sndr& sndr, const Env& env) noexcept;
`
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1533)
*Effects*: Equivalent to:
- [(14.1)](#14.1)
If [*sender-for*](exec.snd.concepts#concept:sender-for "33.9.3Sender concepts[exec.snd.concepts]")<Sndr, continues_on_t> is true, thenreturn Domain(); where Domain is the type of the following expression:[] {auto [_, sch, _] = sndr; return *query-with-default*(get_domain, sch, default_domain());}();
[*Note [1](#note-1)*:
The continues_on algorithm works
in tandem with schedule_from ([[exec.schedule.from]](exec.schedule.from "33.9.12.7execution::schedule_­from"))
to give scheduler authors a way to customize both
how to transition onto (continues_on) and off of (schedule_from)
a given execution context[.](#14.1.sentence-1)
Thus, continues_on ignores the domain of the predecessor and
uses the domain of the destination scheduler to select a customization,
a property that is unique to continues_on[.](#14.1.sentence-2)
That is why it is given special treatment here[.](#14.1.sentence-3)
— *end note*]
- [(14.2)](#14.2)
Otherwise,return Domain(); where Domain is the first of the following expressions
that is well-formed and whose type is not void:
* [(14.2.1)](#14.2.1)
get_domain(get_env(sndr))
* [(14.2.2)](#14.2.2)
*completion-domain*<void>(sndr)
* [(14.2.3)](#14.2.3)
get_domain(env)
* [(14.2.4)](#14.2.4)
get_domain(get_scheduler(env))
* [(14.2.5)](#14.2.5)
default_domain()
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1577)
template<[*callable*](functional.syn#concept:callable "22.10.2Header <functional> synopsis[functional.syn]") Fun>requires is_nothrow_move_constructible_v<Fun>struct *emplace-from* { Fun *fun*; // *exposition only*using type = *call-result-t*<Fun>; constexpr operator type() && noexcept([*nothrow-callable*](functional.syn#concept:nothrow-callable "22.10.2Header <functional> synopsis[functional.syn]")<Fun>) {return std::move(fun)(); }constexpr type operator()() && noexcept([*nothrow-callable*](functional.syn#concept:nothrow-callable "22.10.2Header <functional> synopsis[functional.syn]")<Fun>) {return std::move(fun)(); }};
[*Note [2](#note-2)*:
*emplace-from* is used to emplace non-movable types
into tuple, optional, variant, and similar types[.](#15.sentence-1)
— *end note*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1599)
struct *on-stop-request* { inplace_stop_source& *stop-src*; // *exposition only*void operator()() noexcept { *stop-src*.request_stop(); }};
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1607)
template<class T0, class T1, …, class Tn>struct *product-type* { // *exposition only* T0 t0; // *exposition only* T1 t1; // *exposition only*
Tn tn; // *exposition only*template<size_t I, class Self>constexpr decltype(auto) *get*(this Self&& self) noexcept; // *exposition only*template<class Self, class Fn>constexpr decltype(auto) *apply*(this Self&& self, Fn&& fn) // *exposition only*noexcept(*see below*);};
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1625)
[*Note [3](#note-3)*:
*product-type* is presented here in pseudo-code form
for the sake of exposition[.](#18.sentence-1)
It can be approximated in standard C++ with a tuple-like implementation
that takes care to keep the type an aggregate
that can be used as the initializer of a structured binding declaration[.](#18.sentence-2)
— *end note*]
[*Note [4](#note-4)*:
An expression of type *product-type* is usable as
the initializer of a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#18.sentence-3)
— *end note*]
[🔗](#itemdecl:5)
`template<size_t I, class Self>
constexpr decltype(auto) get(this Self&& self) noexcept;
`
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1644)
*Effects*: Equivalent to:auto& [...ts] = self;return std::forward_like<Self>(ts...[I]);
template<class Self, class Fn>constexpr decltype(auto) *apply*(this Self&& self, Fn&& fn) noexcept(*see below*);
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1659)
*Constraints*: The expression in the return statement below is well-formed[.](#20.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1663)
*Effects*: Equivalent to:auto& [...ts] = self;return std::forward<Fn>(fn)(std::forward_like<Self>(ts)...);
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1671)
*Remarks*: The expression in the noexcept clause is true if the return statement above is not potentially throwing;
otherwise, false[.](#22.sentence-1)
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1678)
Let [*valid-specialization*](#concept:valid-specialization "33.9.2Exposition-only entities[exec.snd.expos]") be the following concept:namespace std::execution {template<template<class...> class T, class... Args>concept [*valid-specialization*](#concept:valid-specialization "33.9.2Exposition-only entities[exec.snd.expos]") = // *exposition only*requires { typename T<Args...>; };}
[🔗](#itemdecl:6)
`template<class Tag, class Data = see below, class... Child>
constexpr auto make-sender(Tag tag, Data&& data, Child&&... child);
`
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1694)
*Mandates*: The following expressions are true:
- [(24.1)](#24.1)
[semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]")<Tag>
- [(24.2)](#24.2)
[*movable-value*](exec.general#concept:movable-value "33.1General[exec.general]")<Data>
- [(24.3)](#24.3)
([sender](exec.snd.concepts#concept:sender "33.9.3Sender concepts[exec.snd.concepts]")<Child> && ...)
- [(24.4)](#24.4)
[dependent_sender](exec.snd.concepts#concept:dependent_sender "33.9.3Sender concepts[exec.snd.concepts]")<Sndr> || [sender_in](exec.snd.concepts#concept:sender_in "33.9.3Sender concepts[exec.snd.concepts]")<Sndr>,
where Sndr is *basic-sender*<Tag, Data,
Child...> as defined below[.](#24.sentence-1)
*Recommended practice*: If evaluation of [sender_in](exec.snd.concepts#concept:sender_in "33.9.3Sender concepts[exec.snd.concepts]")<Sndr> results in
an uncaught exception from
the evaluation of get_completion_signatures<Sndr>(),
the implementation should include information about that exception in
the resulting diagnostic[.](#24.4.sentence-2)
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1714)
*Returns*: A prvalue of
type *basic-sender*<Tag, decay_t<Data>, decay_t<Child>...> that has been direct-list-initialized with the forwarded arguments,
where *basic-sender* is the following exposition-only class template except as noted below[.](#25.sentence-1)
[26](#26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1722)
*Remarks*: The default template argument for the Data template parameter
denotes an unspecified empty trivially copyable class type
that models [semiregular](concepts.object#concept:semiregular "18.6Object concepts[concepts.object]")[.](#26.sentence-1)
namespace std::execution {template<class Tag>concept [*completion-tag*](#concept:completion-tag "33.9.2Exposition-only entities[exec.snd.expos]") = // *exposition only*[same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<Tag, set_value_t> || [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<Tag, set_error_t> || [same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<Tag, set_stopped_t>; struct *default-impls* { // *exposition only*static constexpr auto *get-attrs* = *see below*; // *exposition only*static constexpr auto *get-env* = *see below*; // *exposition only*static constexpr auto *get-state* = *see below*; // *exposition only*static constexpr auto *start* = *see below*; // *exposition only*static constexpr auto *complete* = *see below*; // *exposition only*template<class Sndr, class... Env>static consteval void *check-types*(); // *exposition only*}; template<class Tag>struct *impls-for* : *default-impls* {}; // *exposition only*template<class Sndr, class Rcvr> // *exposition only*using *state-type* = decay_t<*call-result-t*<decltype(*impls-for*<tag_of_t<Sndr>>::*get-state*), Sndr, Rcvr&>>; template<class Index, class Sndr, class Rcvr> // *exposition only*using *env-type* = *call-result-t*<decltype(*impls-for*<tag_of_t<Sndr>>::*get-env*), Index, *state-type*<Sndr, Rcvr>&, const Rcvr&>; template<class Sndr>using *data-type* = decltype(declval<Sndr>().template *get*<1>()); // *exposition only*template<class Sndr, size_t I = 0>using *child-type* = decltype(declval<Sndr>().template *get*<I+2>()); // *exposition only*template<class Sndr>using *indices-for* = remove_reference_t<Sndr>::*indices-for*; // *exposition only*template<class Sndr, class Rcvr>struct *basic-state* { // *exposition only**basic-state*(Sndr&& sndr, Rcvr&& rcvr) noexcept(*see below*): *rcvr*(std::move(rcvr)) , *state*(*impls-for*<tag_of_t<Sndr>>::*get-state*(std::forward<Sndr>(sndr), *rcvr*)) { } Rcvr *rcvr*; // *exposition only**state-type*<Sndr, Rcvr> *state*; // *exposition only*}; template<class Sndr, class Rcvr, class Index>requires [*valid-specialization*](#concept:valid-specialization "33.9.2Exposition-only entities[exec.snd.expos]")<*env-type*, Index, Sndr, Rcvr>struct *basic-receiver* { // *exposition only*using receiver_concept = receiver_t; using *tag-t* = tag_of_t<Sndr>; // *exposition only*using *state-t* = *state-type*<Sndr, Rcvr>; // *exposition only*static constexpr const auto& *complete* = *impls-for*<*tag-t*>::*complete*; // *exposition only*template<class... Args>requires [*callable*](functional.syn#concept:callable "22.10.2Header <functional> synopsis[functional.syn]")<decltype(*complete*), Index, *state-t*&, Rcvr&, set_value_t, Args...>void set_value(Args&&... args) && noexcept {*complete*(Index(), op->*state*, op->*rcvr*, set_value_t(), std::forward<Args>(args)...); }template<class Error>requires [*callable*](functional.syn#concept:callable "22.10.2Header <functional> synopsis[functional.syn]")<decltype(*complete*), Index, *state-t*&, Rcvr&, set_error_t, Error>void set_error(Error&& err) && noexcept {*complete*(Index(), op->*state*, op->*rcvr*, set_error_t(), std::forward<Error>(err)); }void set_stopped() && noexceptrequires [*callable*](functional.syn#concept:callable "22.10.2Header <functional> synopsis[functional.syn]")<decltype(*complete*), Index, *state-t*&, Rcvr&, set_stopped_t> {*complete*(Index(), op->*state*, op->*rcvr*, set_stopped_t()); }auto get_env() const noexcept -> *env-type*<Index, Sndr, Rcvr> {return *impls-for*<tag-t>::*get-env*(Index(), op->*state*, op->*rcvr*); }*basic-state*<Sndr, Rcvr>* *op*; // *exposition only*}; constexpr auto *connect-all* = *see below*; // *exposition only*template<class Sndr, class Rcvr>using *connect-all-result* = *call-result-t*< // *exposition only*decltype(*connect-all*), *basic-state*<Sndr, Rcvr>*, Sndr, *indices-for*<Sndr>>; template<class Sndr, class Rcvr>requires [*valid-specialization*](#concept:valid-specialization "33.9.2Exposition-only entities[exec.snd.expos]")<*state-type*, Sndr, Rcvr> &&[*valid-specialization*](#concept:valid-specialization "33.9.2Exposition-only entities[exec.snd.expos]")<*connect-all-result*, Sndr, Rcvr>struct *basic-operation* : *basic-state*<Sndr, Rcvr> { // *exposition only*using operation_state_concept = operation_state_t; using *tag-t* = tag_of_t<Sndr>; // *exposition only**connect-all-result*<Sndr, Rcvr> *inner-ops*; // *exposition only**basic-operation*(Sndr&& sndr, Rcvr&& rcvr) noexcept(*see below*) // *exposition only*: *basic-state*<Sndr, Rcvr>(std::forward<Sndr>(sndr), std::move(rcvr)), *inner-ops*(*connect-all*(this, std::forward<Sndr>(sndr), *indices-for*<Sndr>())){}void start() & noexcept {auto& [...ops] = *inner-ops*; *impls-for*<tag-t>::*start*(this->*state*, this->*rcvr*, ops...); }}; template<class Tag, class Data, class... Child>struct *basic-sender* : *product-type*<Tag, Data, Child...> { // *exposition only*using sender_concept = sender_t; using *indices-for* = index_sequence_for<Child...>; // *exposition only*decltype(auto) get_env() const noexcept {auto& [_, data, ...child] = *this; return *impls-for*<Tag>::*get-attrs*(data, child...); }template<[*decays-to*](execution.syn#concept:decays-to "33.4Header <execution> synopsis[execution.syn]")<*basic-sender*> Self, [receiver](exec.recv.concepts#concept:receiver "33.7.1Receiver concepts[exec.recv.concepts]") Rcvr>auto connect(this Self&& self, Rcvr rcvr) noexcept(*see below*)-> *basic-operation*<Self, Rcvr> {return {std::forward<Self>(self), std::move(rcvr)}; }template<[*decays-to*](execution.syn#concept:decays-to "33.4Header <execution> synopsis[execution.syn]")<*basic-sender*> Self, class... Env>static constexpr auto get_completion_signatures(); };}
[27](#27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1857)
It is unspecified whether a specialization of *basic-sender* is an aggregate[.](#27.sentence-1)
[28](#28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1861)
An expression of type *basic-sender* is usable as
the initializer of a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#28.sentence-1)
[29](#29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1865)
The expression in the noexcept clause of
the constructor of *basic-state* isis_nothrow_move_constructible_v<Rcvr> &&[*nothrow-callable*](functional.syn#concept:nothrow-callable "22.10.2Header <functional> synopsis[functional.syn]")<decltype(*impls-for*<tag_of_t<Sndr>>::*get-state*), Sndr, Rcvr&> &&([same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<*state-type*<Sndr, Rcvr>, *get-state-result*> || is_nothrow_constructible_v<*state-type*<Sndr, Rcvr>, *get-state-result*>) where *get-state-result* is*call-result-t*<decltype(*impls-for*<tag_of_t<Sndr>>::*get-state*), Sndr, Rcvr&>.
[30](#30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1879)
The object *connect-all* is initialized with
a callable object equivalent to the following lambda:
[🔗](#itemdecl:7)
`[]<class Sndr, class Rcvr, size_t... Is>(
basic-state<Sndr, Rcvr>* op, Sndr&& sndr, index_sequence<Is...>) noexcept(see below)
-> decltype(auto) {
auto& [_, data, ...child] = sndr;
return product-type{connect(
std::forward_like<Sndr>(child),
basic-receiver<Sndr, Rcvr, integral_constant<size_t, Is>>{op})...};
}
`
[31](#31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1894)
*Constraints*: The expression in the return statement is well-formed[.](#31.sentence-1)
[32](#32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1898)
*Remarks*: The expression in the noexcept clause is true if the return statement is not potentially throwing;
otherwise, false[.](#32.sentence-1)
[33](#33)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1905)
The expression in the noexcept clause of
the constructor of *basic-operation* is:is_nothrow_constructible_v<*basic-state*<Self, Rcvr>, Self, Rcvr> &&noexcept(*connect-all*(this, std::forward<Sndr>(sndr), *indices-for*<Sndr>()))
[34](#34)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1913)
The expression in the noexcept clause of
the connect member function of *basic-sender* is:is_nothrow_constructible_v<*basic-operation*<Self, Rcvr>, Self, Rcvr>
[35](#35)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1920)
The member *default-impls*::*get-attrs* is initialized with a callable object equivalent to the following lambda:[](const auto&, const auto&... child) noexcept -> decltype(auto) {if constexpr (sizeof...(child) == 1)return (*FWD-ENV*(get_env(child)), ...); elsereturn env<>();}
[36](#36)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1932)
The member *default-impls*::*get-env* is initialized with a callable object equivalent to the following lambda:[](auto, auto&, const auto& rcvr) noexcept -> decltype(auto) {return *FWD-ENV*(get_env(rcvr));}
[37](#37)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1941)
The member *default-impls*::*get-state* is initialized with a callable object equivalent to the following lambda:[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept -> decltype(auto) {auto& [_, data, ...child] = sndr; return *allocator-aware-forward*(std::forward_like<Sndr>(data), rcvr);}
[38](#38)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1951)
The member *default-impls*::*start* is initialized with a callable object equivalent to the following lambda:[](auto&, auto&, auto&... ops) noexcept -> void {(execution::start(ops), ...);}
[39](#39)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1960)
The member *default-impls*::*complete* is initialized with a callable object equivalent to the following lambda:[]<class Index, class Rcvr, class Tag, class... Args>( Index, auto& state, Rcvr& rcvr, Tag, Args&&... args) noexcept-> void requires [*callable*](functional.syn#concept:callable "22.10.2Header <functional> synopsis[functional.syn]")<Tag, Rcvr, Args...> {static_assert(Index::value == 0);
Tag()(std::move(rcvr), std::forward<Args>(args)...);}
[🔗](#lib:check-types,default-impls)
`template<class Sndr, class... Env>
static consteval void default-impls::check-types();
`
[40](#40)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1979)
Let Is be the pack of integral template arguments of
the integer_sequence specialization denoted by*indices-for*<Sndr>[.](#40.sentence-1)
[41](#41)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1984)
*Effects*: Equivalent to:(get_completion_signatures<*child-type*<Sndr, Is>, *FWD-ENV-T*(Env)...>(), ...);
[42](#42)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L1991)
[*Note [5](#note-5)*:
For any types T and S, and pack E,
let e be the expression*impls-for*<T>::*check-types*<S, E...>()[.](#42.sentence-1)
Then exactly one of the following is true:
- [(42.1)](#42.1)
e is ill-formed, or
- [(42.2)](#42.2)
the evaluation of e exits with an exception, or
- [(42.3)](#42.3)
e is a core constant expression[.](#42.sentence-2)
When e is a core constant expression,
the pack S, E... uniquely determines a set of completion signatures[.](#42.sentence-3)
— *end note*]
[🔗](#lib:get_completion_signatures,basic-sender)
`template<class Tag, class Data, class... Child>
template<class Sndr, class... Env>
constexpr auto basic-sender<Tag, Data, Child...>::get_completion_signatures();
`
[43](#43)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2015)
Let Rcvr be the type of a receiver whose
environment has type E, whereE is the first type in the list Env..., env<>[.](#43.sentence-1)
Let *CHECK-TYPES*() be the expression*impls-for*<Tag>::template *check-types*<
Sndr, E>(), and
let CS be a type determined as follows:
- [(43.1)](#43.1)
If *CHECK-TYPES*() is a core constant expression,
let op be an lvalue subexpression
whose type is connect_result_t<Sndr, Rcvr>[.](#43.1.sentence-1)
Then CS is the specialization of completion_signatures the set of whose template arguments
correspond to the set of completion operations
that are potentially evaluated ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
as a result of evaluating op.start()[.](#43.1.sentence-2)
- [(43.2)](#43.2)
Otherwise, CS is completion_signatures<>[.](#43.2.sentence-1)
[44](#44)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2038)
*Constraints*: *CHECK-TYPES*() is a well-formed expression[.](#44.sentence-1)
[45](#45)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2042)
*Effects*: Equivalent to:*CHECK-TYPES*();return CS();
[46](#46)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2051)
template<class... Fns>struct *overload-set* : Fns... {using Fns::operator()...;};
[47](#47)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2061)
struct *not-a-sender* {using sender_concept = sender_t; template<class Sndr>static consteval auto get_completion_signatures() -> completion_signatures<> {throw *unspecified-exception*(); }}; where *unspecified-exception* is
a type derived from exception[.](#47.sentence-1)
[48](#48)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2078)
constexpr void *decay-copyable-result-datums*(auto cs) { cs.*for-each*([]<class Tag, class... Ts>(Tag(*)(Ts...)) {if constexpr (!(is_constructible_v<decay_t<Ts>, Ts> &&...))throw *unspecified-exception*(); });} where *unspecified-exception* is
a type derived from exception[.](#48.sentence-1)
[🔗](#itemdecl:10)
`template<class T, class Context>
decltype(auto) allocator-aware-forward(T&& obj, Context&& context); // exposition only
`
[49](#49)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2098)
*allocator-aware-forward* is an exposition-only function template
used to either
create a new object of type remove_cvref_t<T> from obj or forward obj depending on whether an allocator is available[.](#49.sentence-1)
If the environment associated with context provides an allocator
(i.e., the expression get_allocator(get_env(context)) is valid),
let *alloc* be the result of this expression
and let P be remove_cvref_t<T>[.](#49.sentence-2)
[50](#50)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2108)
*Returns*:
- [(50.1)](#50.1)
If *alloc* is not defined, returns std::forward<T>(obj),
- [(50.2)](#50.2)
otherwise if P is a specialization of *product-type*,
returns an object of type P whose elements are initialized usingmake_obj_using_allocator<decltype(e)>(std::forward_like<T>(e), *alloc*) where e is the corresponding element of obj,
- [(50.3)](#50.3)
otherwise, returns make_obj_using_allocator<P>(std::forward<T>(obj), *alloc*)[.](#50.sentence-1)