|
4231 | 4231 | whose execution domain does not customize \tcode{when_all_with_variant}.
|
4232 | 4232 | \end{note}
|
4233 | 4233 |
|
4234 |
| -\rSec1[exec.util]{Sender/receiver utilities} |
| 4234 | +\rSec3[exec.into.variant]{\tcode{execution::into_variant}} |
| 4235 | + |
| 4236 | +\pnum |
| 4237 | +\tcode{into_variant} adapts a sender with multiple value completion signatures |
| 4238 | +into a sender with just one value completion signature |
| 4239 | +consisting of a \tcode{variant} of \tcode{tuple}s. |
| 4240 | + |
| 4241 | +\pnum |
| 4242 | +The name \tcode{into_variant} denotes a pipeable sender adaptor object. |
| 4243 | +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. |
| 4244 | +If \tcode{Sndr} does not satisfy \libconcept{sender}, |
| 4245 | +\tcode{into_variant(sndr)} is ill-formed. |
| 4246 | + |
| 4247 | +\pnum |
| 4248 | +Otherwise, the expression \tcode{into_variant(sndr)} |
| 4249 | +is expression-equivalent to: |
| 4250 | +\begin{codeblock} |
| 4251 | +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(into_variant, {}, sndr)) |
| 4252 | +\end{codeblock} |
| 4253 | +except that \tcode{sndr} is only evaluated once. |
| 4254 | + |
| 4255 | +\pnum |
| 4256 | +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} |
| 4257 | +is specialized for \tcode{into_variant} as follows: |
| 4258 | +\begin{codeblock} |
| 4259 | +namespace std::execution { |
| 4260 | + template<> |
| 4261 | + struct @\exposid{impls-for}@<into_variant_t> : @\exposid{default-impls}@ { |
| 4262 | + static constexpr auto @\exposid{get-state}@ = @\seebelow@; |
| 4263 | + static constexpr auto @\exposid{complete}@ = @\seebelow@; |
| 4264 | + }; |
| 4265 | +} |
| 4266 | +\end{codeblock} |
| 4267 | + |
| 4268 | +\pnum |
| 4269 | +The member \tcode{\exposid{impls-for}<into_variant_t>::\exposid{get-state}} |
| 4270 | +is initialized with a callable object equivalent to the following lambda: |
| 4271 | +\begin{codeblock} |
| 4272 | +[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept |
| 4273 | + -> type_identity<value_types_of_t<@\exposid{child-type}@<Sndr>, env_of_t<Rcvr>>> { |
| 4274 | + return {}; |
| 4275 | +} |
| 4276 | +\end{codeblock} |
| 4277 | + |
| 4278 | +\pnum |
| 4279 | +The member \tcode{\exposid{impls-for}<into_variant_t>::\exposid{complete}} |
| 4280 | +is initialized with a callable object equivalent to the following lambda: |
| 4281 | +\begin{codeblock} |
| 4282 | +[]<class State, class Rcvr, class Tag, class... Args>( |
| 4283 | + auto, State, Rcvr& rcvr, Tag, Args&&... args) noexcept -> void { |
| 4284 | + if constexpr (@\libconcept{same_as}@<Tag, set_value_t>) { |
| 4285 | + using variant_type = typename State::type; |
| 4286 | + @\exposid{TRY-SET-VALUE}@(rcvr, variant_type(@\exposid{decayed-tuple}@<Args...>{std::forward<Args>(args)...})); |
| 4287 | + } else { |
| 4288 | + Tag()(std::move(rcvr), std::forward<Args>(args)...); |
| 4289 | + } |
| 4290 | +} |
| 4291 | +\end{codeblock} |
| 4292 | + |
| 4293 | +\rSec3[exec.stopped.opt]{\tcode{execution::stopped_as_optional}} |
| 4294 | + |
| 4295 | +\pnum |
| 4296 | +\tcode{stopped_as_optional} maps a sender's stopped completion operation |
| 4297 | +into a value completion operation as an disengaged \tcode{optional}. |
| 4298 | +The sender's value completion operation |
| 4299 | +is also converted into an \tcode{optional}. |
| 4300 | +The result is a sender that never completes with stopped, |
| 4301 | +reporting cancellation by completing with an disengaged \tcode{optional}. |
| 4302 | + |
| 4303 | +\pnum |
| 4304 | +The name \tcode{stopped_as_optional} denotes a pipeable sender adaptor object. |
| 4305 | +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. |
| 4306 | +The expression \tcode{stopped_as_optional(sndr)} is expression-equivalent to: |
| 4307 | +\begin{codeblock} |
| 4308 | +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(stopped_as_optional, {}, sndr)) |
| 4309 | +\end{codeblock} |
| 4310 | +except that \tcode{sndr} is only evaluated once. |
| 4311 | + |
| 4312 | +\pnum |
| 4313 | +Let \tcode{sndr} and \tcode{env} be subexpressions |
| 4314 | +such that \tcode{Sndr} is \tcode{decltype((sndr))} and |
| 4315 | +\tcode{Env} is \tcode{decltype((env))}. |
| 4316 | +If \tcode{\exposconcept{sender-for}<Sndr, stopped_as_optional_t>} |
| 4317 | +is \tcode{false}, or |
| 4318 | +if the type \tcode{\exposid{single-sender-value-type}<Sndr, Env>} |
| 4319 | +is ill-formed or \tcode{void}, |
| 4320 | +then the expression \tcode{stopped_as_optional.transform_sender(sndr, env)} |
| 4321 | +is ill-formed; |
| 4322 | +otherwise, it is equivalent to: |
| 4323 | +\begin{codeblock} |
| 4324 | +auto&& [_, _, child] = sndr; |
| 4325 | +using V = @\exposid{single-sender-value-type}@<Sndr, Env>; |
| 4326 | +return let_stopped( |
| 4327 | + then(std::forward_like<Sndr>(child), |
| 4328 | + []<class... Ts>(Ts&&... ts) noexcept(is_nothrow_constructible_v<V, Ts...>) { |
| 4329 | + return optional<V>(in_place, std::forward<Ts>(ts)...); |
| 4330 | + }), |
| 4331 | + []() noexcept { return just(optional<V>()); }); |
| 4332 | +\end{codeblock} |
4235 | 4333 |
|
| 4334 | +\rSec3[exec.stopped.err]{\tcode{execution::stopped_as_error}} |
| 4335 | + |
| 4336 | +\pnum |
| 4337 | +\tcode{stopped_as_error} maps an input sender's stopped completion operation |
| 4338 | +into an error completion operation as a custom error type. |
| 4339 | +The result is a sender that never completes with stopped, |
| 4340 | +reporting cancellation by completing with an error. |
| 4341 | + |
| 4342 | +\pnum |
| 4343 | +The name \tcode{stopped_as_error} denotes a pipeable sender adaptor object. |
| 4344 | +For some subexpressions \tcode{sndr} and \tcode{err}, |
| 4345 | +let \tcode{Sndr} be \tcode{decltype((sndr))} and |
| 4346 | +let \tcode{Err} be \tcode{decltype((err))}. |
| 4347 | +If the type \tcode{Sndr} does not satisfy \libconcept{sender} or |
| 4348 | +if the type \tcode{Err} does not satisfy \exposconcept{movable-value}, |
| 4349 | +\tcode{stopped_as_error(sndr, err)} is ill-formed. |
| 4350 | +Otherwise, the expression \tcode{stopped_as_error(sndr, err)} |
| 4351 | +is expression-equivalent to: |
| 4352 | +\begin{codeblock} |
| 4353 | +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(stopped_as_error, err, sndr)) |
| 4354 | +\end{codeblock} |
| 4355 | +except that \tcode{sndr} is only evaluated once. |
| 4356 | + |
| 4357 | +\pnum |
| 4358 | +Let \tcode{sndr} and \tcode{env} be subexpressions |
| 4359 | +such that \tcode{Sndr} is \tcode{decltype((sndr))} and |
| 4360 | +\tcode{Env} is \tcode{decltype((env))}. |
| 4361 | +If \tcode{\exposconcept{sender-for}<Sndr, stopped_as_error_t>} is \tcode{false}, |
| 4362 | +then the expression \tcode{stopped_as_error.transform_sender(sndr, env)} |
| 4363 | +is ill-formed; |
| 4364 | +otherwise, it is equivalent to: |
| 4365 | +\begin{codeblock} |
| 4366 | +auto&& [_, err, child] = sndr; |
| 4367 | +using E = decltype(auto(err)); |
| 4368 | +return let_stopped( |
| 4369 | + std::forward_like<Sndr>(child), |
| 4370 | + [err = std::forward_like<Sndr>(err)]() mutable noexcept(is_nothrow_move_constructible_v<E>) { |
| 4371 | + return just_error(std::move(err)); |
| 4372 | + }); |
| 4373 | +\end{codeblock} |
| 4374 | + |
| 4375 | +\rSec1[exec.util]{Sender/receiver utilities} |
4236 | 4376 |
|
4237 | 4377 | \rSec1[exec.ctx]{Execution contexts}
|
4238 | 4378 |
|
|
0 commit comments