|
1189 | 1189 | template<class O>
|
1190 | 1190 | concept @\deflibconcept{operation_state}@ =
|
1191 | 1191 | @\libconcept{derived_from}@<typename O::operation_state_concept, operation_state_t> &&
|
1192 |
| - is_object_v<O> && |
1193 | 1192 | requires (O& o) {
|
1194 |
| - { start(o) } noexcept; |
| 1193 | + start(o); |
1195 | 1194 | };
|
1196 | 1195 | }
|
1197 | 1196 | \end{codeblock}
|
|
1279 | 1278 | the expression \tcode{\exposid{FWD-ENV}(env).query(q, as...)} is ill-formed
|
1280 | 1279 | if \tcode{forwarding_query(q)} is \tcode{false};
|
1281 | 1280 | otherwise, it is expression-equivalent to \tcode{env.query(q, as...)}.
|
| 1281 | +The type \tcode{\exposid{FWD-ENV-T}(Env)} is |
| 1282 | +\tcode{decltype(\exposid{FWD-ENV}(declval<Env>()))}. |
1282 | 1283 |
|
1283 | 1284 | \pnum
|
1284 | 1285 | For a query object \tcode{q} and \tcode{a} subexpression \tcode{v},
|
|
1946 | 1947 | @\exposconcept{is-sender}@<Sndr> ||
|
1947 | 1948 | @\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<env<>>>; // \ref{exec.awaitable}
|
1948 | 1949 |
|
| 1950 | + template<class Sndr> |
| 1951 | + inline constexpr bool enable_sender = @\exposconcept{enable-sender}@<Sndr>; |
| 1952 | + |
1949 | 1953 | template<class Sndr>
|
1950 | 1954 | concept @\deflibconcept{sender}@ =
|
1951 |
| - bool(@\exposconcept{enable-sender}@<remove_cvref_t<Sndr>>) && |
| 1955 | + enable_sender<remove_cvref_t<Sndr>> && |
1952 | 1956 | requires (const remove_cvref_t<Sndr>& sndr) {
|
1953 | 1957 | { get_env(sndr) } -> @\exposconcept{queryable}@;
|
1954 | 1958 | } &&
|
|
1989 | 1993 | starting the resulting operation state
|
1990 | 1994 | are permissible completions for \tcode{Sndr} and \tcode{Env}.
|
1991 | 1995 |
|
| 1996 | +\pnum |
| 1997 | +\remarks |
| 1998 | +Pursuant to \ref{namespace.std}, |
| 1999 | +users may specialize \tcode{enable_sender} to |
| 2000 | +\tcode{true} for cv-unqualified program-defined types that |
| 2001 | +model \libconcept{sender}, and |
| 2002 | +\tcode{false} for types that do not. |
| 2003 | +Such specializations shall |
| 2004 | +be usable in constant expressions\iref{expr.const} and |
| 2005 | +have type \tcode{const bool}. |
| 2006 | + |
1992 | 2007 | \pnum
|
1993 | 2008 | A type models
|
1994 | 2009 | the exposition-only concept \defexposconcept{valid-completion-signatures}
|
|
2141 | 2156 | }
|
2142 | 2157 |
|
2143 | 2158 | template<@\exposconcept{has-as-awaitable}@<Derived> T>
|
2144 |
| - decltype(auto) await_transform(T&& value) |
2145 |
| - noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>()))) { |
| 2159 | + auto await_transform(T&& value) |
| 2160 | + noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>()))) |
| 2161 | + -> decltype(std::forward<T>(value).as_awaitable(declval<Derived&>())) { |
2146 | 2162 | return std::forward<T>(value).as_awaitable(static_cast<Derived&>(*this));
|
2147 | 2163 | }
|
2148 | 2164 | };
|
|
2231 | 2247 | tag_of_t<Sndr>().transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env))
|
2232 | 2248 | \end{codeblock}
|
2233 | 2249 | if that expression is well-formed;
|
2234 |
| -otherwise, \tcode{static_cast<Env>(std::forward<Env>(env))}. |
| 2250 | +otherwise, \tcode{\exposid{FWD-ENV}(std::forward<Env>(env))}. |
2235 | 2251 |
|
2236 | 2252 | \pnum
|
2237 | 2253 | \mandates
|
|
2561 | 2577 | \item
|
2562 | 2578 | Otherwise, \tcode{\exposid{connect-awaitable}(new_sndr, rcvr)}.
|
2563 | 2579 | \end{itemize}
|
| 2580 | +%%FIXME: This sentence should be joined with the previous sentences; |
| 2581 | +%%FIXME: how to do that with the embeded "madates"?? |
| 2582 | +Except that \tcode{rcvr} is evaluated only once. |
2564 | 2583 |
|
2565 | 2584 | \mandates
|
2566 | 2585 | \tcode{\libconcept{sender}<Sndr> \&\& \libconcept{receiver}<Rcvr>} is \tcode{true}.
|
|
2995 | 3014 | is initialized with a callable object equivalent to the following lambda:
|
2996 | 3015 | \begin{codeblock}
|
2997 | 3016 | []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(@\seebelow@)
|
2998 |
| - requires @\libconcept{sender_in}@<@\exposid{child-type}@<Sndr>, env_of_t<Rcvr>> { |
| 3017 | + requires @\libconcept{sender_in}@<@\exposid{child-type}@<Sndr>, @\exposid{FWD-ENV-T}@(env_of_t<Rcvr>)> { |
2999 | 3018 |
|
3000 | 3019 | auto& [_, sch, child] = sndr;
|
3001 | 3020 |
|
|
3025 | 3044 | \pnum
|
3026 | 3045 | Let \tcode{Sigs} be
|
3027 | 3046 | a pack of the arguments to the \tcode{completion_signatures} specialization
|
3028 |
| -named by \tcode{completion_signatures_of_t<\exposid{child-type}<Sndr>, env_of_t<Rcvr>>}. |
3029 |
| -Let \exposid{as-tuple} be an alias template |
3030 |
| -that transforms a completion signature \tcode{Tag(Args...)} into |
3031 |
| -the tuple specialization \tcode{\exposid{decayed-tuple}<Tag, Args...>}. |
| 3047 | +named by \tcode{completion_signatures_of_t<\exposid{child-type}<Sndr>, \exposid{FWD-ENV-T}(env_of_t<Rcvr>)>}. |
| 3048 | +Let \exposid{as-tuple} be an alias template such that |
| 3049 | +\tcode{\exposid{as-tuple}<Tag(Args...)>} denotes |
| 3050 | +the type \tcode{\exposid{decayed-tuple}<Tag, Args...>}, and |
| 3051 | +let \exposid{is-no\-throw-decay-copy-sig} be a variable template such that |
| 3052 | +\tcode{auto(\exposid{is-nothrow-decay-copy-sig}<Tag(Args...\linebreak{})>)} is |
| 3053 | +a constant expression of type \tcode{bool} and |
| 3054 | +equal to \tcode{(is_nothrow_constructible_v<decay_t<Args>, Args> \&\& ...)}. |
| 3055 | +Let \exposid{error-completion} be a pack consisting of |
| 3056 | +the type \tcode{set_error_t(exception_ptr)} |
| 3057 | +if \tcode{(\exposid{is-nothrow-decay-copy-sig}<Sigs> \&\&...)} is \tcode{false}, |
| 3058 | +and an empty pack otherwise. |
3032 | 3059 | Then \tcode{variant_t} denotes
|
3033 |
| -the type \tcode{variant<monostate, \exposid{as-tuple}<Sigs>...>}, |
| 3060 | +the type \tcode{variant<monostate, \exposid{as-tuple}<Sigs>..., \exposid{error-completion}...>}, |
3034 | 3061 | except with duplicate types removed.
|
3035 | 3062 |
|
3036 | 3063 | \pnum
|
|
3081 | 3108 | []<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
|
3082 | 3109 | -> void {
|
3083 | 3110 | using result_t = @\exposid{decayed-tuple}@<Tag, Args...>;
|
3084 |
| - constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>; |
| 3111 | + constexpr bool nothrow = (is_nothrow_constructible_v<decay_t<Args>, Args> && ...); |
3085 | 3112 |
|
3086 | 3113 | try {
|
3087 | 3114 | state.@\exposid{async-result}@.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
|
3088 | 3115 | } catch (...) {
|
3089 |
| - if constexpr (!nothrow) { |
3090 |
| - set_error(std::move(rcvr), current_exception()); |
3091 |
| - return; |
3092 |
| - } |
| 3116 | + if constexpr (!nothrow) |
| 3117 | + state.@\exposid{async-result}@.template emplace<tuple<set_error_t, |
| 3118 | + exception_ptr>>(set_error, current_exception()); |
3093 | 3119 | }
|
3094 | 3120 | start(state.@\exposid{op-state}@);
|
3095 | 3121 | };
|
|
3493 | 3519 | \item
|
3494 | 3520 | given a query object \tcode{q},
|
3495 | 3521 | the expression \tcode{e.query(q)} is expression-equivalent
|
3496 |
| -to \tcode{\exposid{env}.query(q)} if that expression is valid, |
3497 |
| -otherwise \tcode{e.query(q)} is expression-equivalent |
3498 |
| -to \tcode{get_env(\exposid{rcvr}).query(q)}. |
| 3522 | +to \tcode{\exposid{env}.query(q)} if that expression is valid; |
| 3523 | +otherwise, |
| 3524 | +if the type of \tcode{q} satisfies \exposconcept{forwarding-query}, |
| 3525 | +\tcode{e.query(q)} is expression-equivalent |
| 3526 | +to \tcode{get_env(\exposid{rcvr}).query(q)}; |
| 3527 | +otherwise, |
| 3528 | +\tcode{e.query(q)} is ill-formed. |
3499 | 3529 | \end{itemize}
|
3500 | 3530 |
|
3501 | 3531 | \pnum
|
|
3522 | 3552 | \pnum
|
3523 | 3553 | Let \tcode{Sigs} be a pack of the arguments
|
3524 | 3554 | to the \tcode{completion_signatures} specialization named by
|
3525 |
| -\tcode{completion_signatures_of_t<\exposid{child-type}<Sndr>, env_of_t<Rcvr>>}. |
| 3555 | +\tcode{completion_signatures_of_t<\exposid{child-type}<Sndr>, \exposid{FWD-ENV-T}(env_of_t<Rcvr>)>}. |
3526 | 3556 | Let \tcode{LetSigs} be a pack of those types in \tcode{Sigs}
|
3527 | 3557 | with a return type of \tcode{\exposid{decayed-typeof}<\exposid{set-cpo}>}.
|
3528 | 3558 | Let \exposid{as-tuple} be an alias template
|
|
3540 | 3570 | Then \tcode{ops2_variant_t} denotes
|
3541 | 3571 | the type
|
3542 | 3572 | \begin{codeblock}
|
3543 |
| -variant<monostate, connect_result_t<@\exposid{as-sndr2}@<LetSigs>, @\exposid{receiver2}@<Rcvr, Env>>...> |
| 3573 | +variant<monostate, connect_result_t<@\exposid{as-sndr2}@<LetSigs>, @\exposid{receiver2}@<Rcvr, env_t>>...> |
3544 | 3574 | \end{codeblock}
|
3545 | 3575 | except with duplicate types removed.
|
3546 | 3576 |
|
|
3585 | 3615 | is \tcode{false},
|
3586 | 3616 | then the expression \tcode{\exposid{let-cpo}.transform_env(sndr, env)}
|
3587 | 3617 | is ill-formed.
|
3588 |
| -Otherwise, it is equal to |
3589 |
| -\tcode{\exposid{JOIN-ENV}(\exposid{let-env}(sndr), \exposid{FWD-ENV}(env))}. |
| 3618 | +Otherwise, it is equal to: |
| 3619 | +\begin{codeblock} |
| 3620 | +auto& [_, _, child] = sndr; |
| 3621 | +return @\exposid{JOIN-ENV}@(@\exposid{let-env}@(child), @\exposid{FWD-ENV}@(env)); |
| 3622 | +\end{codeblock} |
3590 | 3623 |
|
3591 | 3624 | \pnum
|
3592 | 3625 | Let the subexpression \tcode{out_sndr} denote
|
|
4153 | 4186 | \tcode{e.query(get_stop_token)} is expression-equivalent to
|
4154 | 4187 | \tcode{state.\exposid{stop-src}.get_token()}, and
|
4155 | 4188 | \item
|
4156 |
| -given a query object \tcode{q} with type other than \cv{} \tcode{stop_token_t}, |
| 4189 | +given a query object \tcode{q} with type other than \cv{} \tcode{stop_token_t} |
| 4190 | +and whose type satisfies \exposconceptx{forwarding-que\-ry}{forwarding-query}, |
4157 | 4191 | \tcode{e.query(q)} is expression-equivalent to \tcode{get_env(rcvr).query(q)}.
|
4158 | 4192 | \end{itemize}
|
4159 | 4193 |
|
|
4162 | 4196 | is initialized with a callable object
|
4163 | 4197 | equivalent to the following lambda expression:
|
4164 | 4198 | \begin{codeblock}
|
4165 |
| -[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(@$e$@) -> decltype(@$e$@) { |
| 4199 | +[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(noexcept(@$e$@)) -> decltype(@$e$@) { |
4166 | 4200 | return @$e$@;
|
4167 | 4201 | }
|
4168 | 4202 | \end{codeblock}
|
|
4180 | 4214 |
|
4181 | 4215 | template<class Rcvr>
|
4182 | 4216 | struct @\exposid{make-state}@ {
|
4183 |
| - template<@\exposconcept{max-1-sender-in}@<env_of_t<Rcvr>>... Sndrs> |
| 4217 | + template<@\exposconcept{max-1-sender-in}@<@\exposid{FWD-ENV-T}@(env_of_t<Rcvr>)>... Sndrs> |
4184 | 4218 | auto operator()(auto, auto, Sndrs&&... sndrs) const {
|
4185 | 4219 | using values_tuple = @\seebelow@;
|
4186 | 4220 | using errors_variant = @\seebelow@;
|
|
4217 | 4251 | \pnum
|
4218 | 4252 | The alias \tcode{values_tuple} denotes the type
|
4219 | 4253 | \begin{codeblock}
|
4220 |
| -tuple<value_types_of_t<Sndrs, env_of_t<Rcvr>, @\exposid{decayed-tuple}@, optional>...> |
| 4254 | +tuple<value_types_of_t<Sndrs, @\exposid{FWD-ENV-T}@(env_of_t<Rcvr>), @\exposid{decayed-tuple}@, optional>...> |
4221 | 4255 | \end{codeblock}
|
4222 | 4256 | if that type is well-formed; otherwise, \tcode{tuple<>}.
|
4223 | 4257 |
|
|
4405 | 4439 | is initialized with a callable object equivalent to the following lambda:
|
4406 | 4440 | \begin{codeblock}
|
4407 | 4441 | []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept
|
4408 |
| - -> type_identity<value_types_of_t<@\exposid{child-type}@<Sndr>, env_of_t<Rcvr>>> { |
| 4442 | + -> type_identity<value_types_of_t<@\exposid{child-type}@<Sndr>, @\exposid{FWD-ENV-T}@(env_of_t<Rcvr>)>> { |
4409 | 4443 | return {};
|
4410 | 4444 | }
|
4411 | 4445 | \end{codeblock}
|
|
4450 | 4484 | \tcode{Env} is \tcode{decltype((env))}.
|
4451 | 4485 | If \tcode{\exposconcept{sender-for}<Sndr, stopped_as_optional_t>}
|
4452 | 4486 | is \tcode{false}, or
|
4453 |
| -if the type \tcode{\exposid{single-sender-value-type}<Sndr, Env>} |
| 4487 | +if the type \tcode{\exposid{single-sender-value-type}<\linebreak{}\exposid{child-type}<Sndr>, \exposid{FWD-ENV-T}(Env)>} |
4454 | 4488 | is ill-formed or \tcode{void},
|
4455 |
| -then the expression \tcode{stopped_as_optional.transform_sender(sndr, env)} |
| 4489 | +then the expression \tcode{stopped_as_optional.\linebreak{}transform_sender(sndr, env)} |
4456 | 4490 | is ill-formed;
|
4457 | 4491 | otherwise, it is equivalent to:
|
4458 | 4492 | \begin{codeblock}
|
4459 | 4493 | auto&& [_, _, child] = sndr;
|
4460 |
| -using V = @\exposid{single-sender-value-type}@<Sndr, Env>; |
| 4494 | +using V = @\exposid{single-sender-value-type}@<@\exposid{child-type}@<Sndr>, @\exposid{FWD-ENV-T}@(Env)>; |
4461 | 4495 | return let_stopped(
|
4462 | 4496 | then(std::forward_like<Sndr>(child),
|
4463 | 4497 | []<class... Ts>(Ts&&... ts) noexcept(is_nothrow_constructible_v<V, Ts...>) {
|
|
0 commit comments