Skip to content

Commit 9d39eaf

Browse files
committed
fixup: add upto 34.9.11.8
1 parent fc39a1a commit 9d39eaf

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed

source/exec.tex

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3286,6 +3286,207 @@
32863286
forwards all other completion operations unchanged.
32873287
\end{itemize}
32883288

3289+
\rSec3[exec.let]{\tcode{execution::let_value}, \tcode{execution::let_error}, \tcode{execution::let_stopped}}
3290+
3291+
\pnum
3292+
\tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped} transform
3293+
a sender's value, error, and stopped completions, respectively,
3294+
into a new child asynchronous operation
3295+
by passing the sender's result datums to a user-specified callable,
3296+
which returns a new sender that is connected and started.
3297+
3298+
\pnum
3299+
For \tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped},
3300+
let \exposid{set-cpo} be
3301+
\tcode{set_value}, \tcode{set_error}, and \tcode{set_stopped}, respectively.
3302+
Let the expression \exposid{let-cpo} be one of
3303+
\tcode{let_value}, \tcode{let_error}, or \tcode{let_stopped}.
3304+
For a subexpression \tcode{sndr},
3305+
let \tcode{\exposid{let-env}(sndr)} be expression-equivalent to
3306+
the first well-formed expression below:
3307+
\begin{itemize}
3308+
\item
3309+
\tcode{SCHED-ENV(get_completion_scheduler<\exposid{decayed-typeof}<\exposid{set-cpo}>>(get_env(sndr)))}
3310+
\item
3311+
\tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))}
3312+
\item
3313+
\tcode{(void(sndr), empty_env\{\})}
3314+
\end{itemize}
3315+
3316+
\pnum
3317+
The names \tcode{let_value}, \tcode{let_error}, and \tcode{let_stopped} denote
3318+
pipeable sender adaptor objects.
3319+
For subexpressions \tcode{sndr} and \tcode{f},
3320+
let \tcode{F} be the decayed type of \tcode{f}.
3321+
If \tcode{decltype((sndr))} does not satisfy \libconcept{sender} or
3322+
if \tcode{decltype((f))} does not satisfy \exposconcept{movable-value},
3323+
the expression \tcode{\exposid{let-cpo}(sndr, f)} is ill-formed.
3324+
If \tcode{F} does not satisfy \libconcept{invocable},
3325+
the expression \tcode{let_stopped(sndr, f)} is ill-formed.
3326+
3327+
\pnum
3328+
Otherwise,
3329+
the expression \tcode{\exposid{let-cpo}(sndr, f)} is expression-equivalent to:
3330+
\begin{codeblock}
3331+
transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(@\exposid{let-cpo}@, f, sndr))
3332+
\end{codeblock}
3333+
except that \tcode{sndr} is evaluated only once.
3334+
3335+
\pnum
3336+
The exposition-only class template \exposid{impls-for}\iref{exec.snd.general}
3337+
is specialized for \exposid{let-cpo} as follows:
3338+
\begin{codeblock}
3339+
namespace std::execution {
3340+
template<class State, class Rcvr, class... Args>
3341+
void @\exposid{let-bind}@(State& state, Rcvr& rcvr, Args&&... args); // \expos
3342+
3343+
template<>
3344+
struct @\exposid{impls-for}@<@\exposid{decayed-typeof}@<@\exposid{let-cpo}@>> : @\exposid{default-impls}@ {
3345+
static constexpr auto @\exposid{get-state}@ = @\seebelow@;
3346+
static constexpr auto @\exposid{complete}@ = @\seebelow@;
3347+
};
3348+
}
3349+
\end{codeblock}
3350+
3351+
\pnum
3352+
Let \exposid{receiver2} denote the following exposition-only class template:
3353+
\begin{codeblock}
3354+
namespace std::execution {
3355+
template<class Rcvr, class Env>
3356+
struct @\exposid{receiver2}@ {
3357+
using receiver_concept = receiver_t;
3358+
3359+
template<class... Args>
3360+
void set_value(Args&&... args) && noexcept {
3361+
execution::set_value(std::move(@\exposid{rcvr}@), std::forward<Args>(args)...);
3362+
}
3363+
3364+
template<class Error>
3365+
void set_error(Error&& err) && noexcept {
3366+
execution::set_error(std::move(@\exposid{rcvr}@), std::forward<Error>(err));
3367+
}
3368+
3369+
void set_stopped() && noexcept {
3370+
execution::set_stopped(std::move(@\exposid{rcvr}@));
3371+
}
3372+
3373+
decltype(auto) get_env() const noexcept {
3374+
return @\exposid{JOIN-ENV}@(@\exposid{env}@, @\exposid{FWD-ENV}@(execution::get_env(@\exposid{rcvr}@)));
3375+
}
3376+
3377+
Rcvr& @\exposid{rcvr}@; // exposition only
3378+
Env @\exposid{env}@; // exposition only
3379+
};
3380+
}
3381+
\end{codeblock}
3382+
3383+
\pnum
3384+
\tcode{\exposid{impls-for}<\exposid{decayed-typeof}<\exposid{let-cpo}>>::\exposid{get-state}}
3385+
is initialized with a callable object equivalent to the following:
3386+
\begin{codeblock}
3387+
[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) requires @\seebelow@ {
3388+
auto& [_, fn, child] = sndr;
3389+
using fn_t = decay_t<decltype(fn)>;
3390+
using env_t = decltype(@\exposid{let-env}@(child));
3391+
using args_variant_t = @\seebelow@;
3392+
using ops2_variant_t = @\seebelow@;
3393+
3394+
struct @\exposid{state-type}@ {
3395+
fn_t @\exposid{fn}@; // exposition only
3396+
env_t @\exposid{env}@; // exposition only
3397+
args_variant_t @\exposid{args}@; // exposition only
3398+
ops2_variant_t @\exposid{ops2}@; // exposition only
3399+
};
3400+
return @\exposid{state-type}@{std::forward_like<Sndr>(fn), @\exposid{let-env}@(child), {}, {}};
3401+
}
3402+
\end{codeblock}
3403+
3404+
\pnum
3405+
Let \tcode{Sigs} be a pack of the arguments
3406+
to the \tcode{completion_signatures} specialization named by
3407+
\tcode{completion_signatures_of_t<\exposid{child-type}<Sndr>, env_of_t<Rcvr>>}.
3408+
Let \tcode{LetSigs} be a pack of those types in \tcode{Sigs}
3409+
with a return type of \tcode{\exposid{decayed-typeof}<\exposid{set-cpo}>}.
3410+
Let \exposid{as-tuple} be an alias template
3411+
such that \tcode{\exposid{as-tuple}<Tag(Args...)>} denotes
3412+
the type \tcode{\exposid{decayed-tuple}<Args...>}.
3413+
Then \tcode{args_variant_t} denotes
3414+
the type \tcode{variant<monostate, \exposid{as-tuple}<LetSigs>...>}
3415+
except with duplicate types removed.
3416+
3417+
\pnum
3418+
Given a type \tcode{Tag} and a pack \tcode{Args},
3419+
let \exposid{as-sndr2} be an alias template
3420+
such that \tcode{\exposid{as-sndr2}<Tag(Args...)>} denotes
3421+
the type \tcode{\exposid{call-result-t}<Fn, decay_t<Args>\&...>}.
3422+
Then \tcode{ops2_variant_t} denotes
3423+
the type \tcode{variant<monostate, connect_result_t<\exposid{as-sndr2}<LetSigs>, \exposid{receiver2}<Rcvr, Env>>...>}
3424+
except with duplicate types removed.
3425+
3426+
\pnum
3427+
The \grammarterm{requires-clause} constraining the above lambda is satisfied
3428+
if and only if
3429+
the types \tcode{args_variant_t} and \tcode{ops2_variant_t} are well-formed.
3430+
3431+
\pnum
3432+
The exposition-only function template \exposid{let-bind}
3433+
has effects equivalent to:
3434+
\begin{codeblock}
3435+
using args_t = @\exposid{decayed-tuple}@<Args...>;
3436+
auto mkop2 = [&] {
3437+
return connect(
3438+
apply(std::move(state.fn),
3439+
state.args.template emplace<args_t>(std::forward<Args>(args)...)),
3440+
@\exposid{receiver2}@{rcvr, std::move(state.env)});
3441+
};
3442+
start(state.ops2.template emplace<decltype(mkop2())>(@\exposid{emplace-from}@{mkop2}));
3443+
\end{codeblock}
3444+
3445+
\pnum
3446+
\tcode{\exposid{impls-for}<\exposid{decayed-typeof}<let-cpo>>::\exposid{complete}}
3447+
is initialized with a callable object equivalent to the following:
3448+
\begin{codeblock}
3449+
[]<class Tag, class... Args>
3450+
(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void {
3451+
if constexpr (@\libconcept{same_as}@<Tag, @\exposid{decayed-typeof}@<@\exposid{set-cpo}@>>) {
3452+
@\exposid{TRY-EVAL}@(rcvr, @\exposid{let-bind}@(state, rcvr, std::forward<Args>(args)...));
3453+
} else {
3454+
Tag()(std::move(rcvr), std::forward<Args>(args)...);
3455+
}
3456+
}
3457+
\end{codeblock}
3458+
3459+
\pnum
3460+
Let \tcode{sndr} and \tcode{env} be subexpressions, and
3461+
let \tcode{Sndr} be \tcode{decltype((sndr))}.
3462+
If
3463+
\tcode{\exposconcept{sender-for<}Sndr, \exposid{decayed-typeof}<\exposid{let-cpo}>>}
3464+
is \tcode{false},
3465+
then the expression \tcode{\exposid{let-cpo}.transform_env(sndr, env)}
3466+
is ill-formed.
3467+
Otherwise, it is equal to
3468+
\tcode{\exposid{JOIN-ENV}(\exposid{let-env}(sndr), \exposid{FWD-ENV}(env))}.
3469+
3470+
\pnum
3471+
Let the subexpression \tcode{out_sndr} denote
3472+
the result of the invocation \tcode{\exposid{let-cpo}(sndr, f)} or
3473+
an object equal to such, and
3474+
let the subexpression \tcode{rcvr} denote a receiver
3475+
such that the expression \tcode{connect(out_sndr, rcvr)} is well-formed.
3476+
The expression \tcode{connect(out_sndr, rcvr)} has undefined behavior
3477+
unless it creates an asynchronous operation\iref{exec.async.ops} that,
3478+
when started:
3479+
\begin{itemize}
3480+
\item
3481+
invokes \tcode{f} when \exposid{set-cpo} is called
3482+
with \tcode{sndr}'s result datums,
3483+
\item
3484+
makes its completion dependent on
3485+
the completion of a sender returned by \tcode{f}, and
3486+
\item
3487+
propagates the other completion operations sent by \tcode{sndr}.
3488+
\end{itemize}
3489+
32893490
\rSec1[exec.util]{Sender/receiver utilities}
32903491

32913492

0 commit comments

Comments
 (0)