|
465 | 465 | template<class CPO>
|
466 | 466 | constexpr get_completion_scheduler_t<CPO> @\libglobal{get_completion_scheduler}@{};
|
467 | 467 |
|
468 |
| - struct @\libglobal{empty_env}@ {}; |
469 | 468 | struct @\libglobal{get_env_t}@ { @\unspec@ };
|
470 | 469 | inline constexpr get_env_t @\libglobal{get_env}@{};
|
471 | 470 |
|
472 | 471 | template<class T>
|
473 | 472 | using @\libglobal{env_of_t}@ = decltype(get_env(declval<T>()));
|
474 | 473 |
|
| 474 | + // \ref{exec.prop}, class template \tcode{prop} |
| 475 | + template<class QueryTag, class ValueType> |
| 476 | + struct prop; |
| 477 | + |
| 478 | + // \ref{exec.env}, class template \tcode{env} |
| 479 | + template<@\exposconcept{queryable}@... Envs> |
| 480 | + struct env; |
| 481 | + |
475 | 482 | // \ref{exec.domain.default}, execution domains
|
476 | 483 | struct default_domain;
|
477 | 484 |
|
|
513 | 520 | template<class Sndr>
|
514 | 521 | concept @\libconcept{sender}@ = @\seebelow@;
|
515 | 522 |
|
516 |
| - template<class Sndr, class Env = empty_env> |
| 523 | + template<class Sndr, class Env = env<>> |
517 | 524 | concept @\libconcept{sender_in}@ = @\seebelow@;
|
518 | 525 |
|
519 | 526 | template<class Sndr, class Rcvr>
|
|
526 | 533 | struct get_completion_signatures_t;
|
527 | 534 | inline constexpr get_completion_signatures_t get_completion_signatures {};
|
528 | 535 |
|
529 |
| - template<class Sndr, class Env = empty_env> |
| 536 | + template<class Sndr, class Env = env<>> |
530 | 537 | requires @\libconcept{sender_in}@<Sndr, Env>
|
531 | 538 | using completion_signatures_of_t = @\exposid{call-result-t}@<get_completion_signatures_t, Sndr, Env>;
|
532 | 539 |
|
|
536 | 543 | template<class... Ts>
|
537 | 544 | using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos
|
538 | 545 |
|
539 |
| - template<class Sndr, class Env = empty_env, |
| 546 | + template<class Sndr, class Env = env<>, |
540 | 547 | template<class...> class Tuple = @\exposid{decayed-tuple}@,
|
541 | 548 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
542 | 549 | requires @\libconcept{sender_in}@<Sndr, Env>
|
543 | 550 | using value_types_of_t = @\seebelow@;
|
544 | 551 |
|
545 |
| - template<class Sndr, class Env = empty_env, |
| 552 | + template<class Sndr, class Env = env<>, |
546 | 553 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
547 | 554 | requires @\libconcept{sender_in}@<Sndr, Env>
|
548 | 555 | using error_types_of_t = @\seebelow@;
|
549 | 556 |
|
550 |
| - template<class Sndr, class Env = empty_env> |
| 557 | + template<class Sndr, class Env = env<>> |
551 | 558 | requires @\libconcept{sender_in}@<Sndr, Env>
|
552 | 559 | constexpr bool sends_stopped = @\seebelow@;
|
553 | 560 |
|
|
661 | 668 |
|
662 | 669 | template<
|
663 | 670 | @\libconcept{sender}@ Sndr,
|
664 |
| - class Env = empty_env, |
| 671 | + class Env = env<>, |
665 | 672 | @\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>,
|
666 | 673 | template<class...> class SetValue = @\seebelow@,
|
667 | 674 | template<class> class SetError = @\seebelow@,
|
|
833 | 840 | The type of the expression above satisfies
|
834 | 841 | \exposconcept{queryable}\iref{exec.queryable}.
|
835 | 842 | \item
|
836 |
| -Otherwise, \tcode{empty_env\{\}}. |
| 843 | +Otherwise, \tcode{env<>\{\}}. |
837 | 844 | \end{itemize}
|
838 | 845 |
|
839 | 846 | \pnum
|
|
1785 | 1792 | if constexpr (sizeof...(child) == 1)
|
1786 | 1793 | return (@\exposid{FWD-ENV}@(get_env(child)), ...);
|
1787 | 1794 | else
|
1788 |
| - return empty_env(); |
| 1795 | + return env<>(); |
1789 | 1796 | }
|
1790 | 1797 | \end{codeblock}
|
1791 | 1798 |
|
|
1929 | 1936 | template<class Sndr>
|
1930 | 1937 | concept @\defexposconcept{enable-sender}@ = // \expos
|
1931 | 1938 | @\exposconcept{is-sender}@<Sndr> ||
|
1932 |
| - @\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<empty_env>>; // \ref{exec.awaitable} |
| 1939 | + @\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<env<>>>; // \ref{exec.awaitable} |
1933 | 1940 |
|
1934 | 1941 | template<class Sndr>
|
1935 | 1942 | concept @\deflibconcept{sender}@ =
|
|
1940 | 1947 | @\libconcept{move_constructible}@<remove_cvref_t<Sndr>> &&
|
1941 | 1948 | @\libconcept{constructible_from}@<remove_cvref_t<Sndr>, Sndr>;
|
1942 | 1949 |
|
1943 |
| - template<class Sndr, class Env = empty_env> |
| 1950 | + template<class Sndr, class Env = env<>> |
1944 | 1951 | concept @\deflibconcept{sender_in}@ =
|
1945 | 1952 | @\libconcept{sender}@<Sndr> &&
|
1946 | 1953 | @\exposconcept{queryable}@<Env> &&
|
|
1998 | 2005 | value_types_of_t<Sndr, Env, @\exposid{value-signature}@, type_identity_t>);
|
1999 | 2006 |
|
2000 | 2007 | template<class Sndr, class... Values>
|
2001 |
| - concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, empty_env, Values...>; |
| 2008 | + concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, env<>, Values...>; |
2002 | 2009 | }
|
2003 | 2010 | \end{codeblock}
|
2004 | 2011 |
|
|
2680 | 2687 | \tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}.
|
2681 | 2688 | \item
|
2682 | 2689 | A parent sender with more than one child sender has
|
2683 |
| -an associated attributes object equal to \tcode{empty_env\{\}}. |
| 2690 | +an associated attributes object equal to \tcode{env<>\{\}}. |
2684 | 2691 | \item
|
2685 | 2692 | When a parent sender is connected to a receiver \tcode{rcvr},
|
2686 | 2693 | any receiver used to connect a child sender has
|
|
3401 | 3408 | \item
|
3402 | 3409 | \tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))}
|
3403 | 3410 | \item
|
3404 |
| -\tcode{(void(sndr), empty_env\{\})} |
| 3411 | +\tcode{(void(sndr), env<>\{\})} |
3405 | 3412 | \end{itemize}
|
3406 | 3413 |
|
3407 | 3414 | \pnum
|
|
4114 | 4121 | \begin{codeblock}
|
4115 | 4122 | [](auto&&, auto&&... child) noexcept {
|
4116 | 4123 | if constexpr (@\libconcept{same_as}@<CD, default_domain>) {
|
4117 |
| - return empty_env(); |
| 4124 | + return env<>(); |
4118 | 4125 | } else {
|
4119 | 4126 | return @\exposid{MAKE-ENV}@(get_domain, CD());
|
4120 | 4127 | }
|
|
4852 | 4859 | template<@\exposconcept{completion-signature}@... Fns>
|
4853 | 4860 | struct completion_signatures {};
|
4854 | 4861 |
|
4855 |
| - template<class Sndr, |
4856 |
| - class Env = empty_env, |
| 4862 | + template<class Sndr, class Env = env<>, |
4857 | 4863 | template<class...> class Tuple = @\exposid{decayed-tuple}@,
|
4858 | 4864 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
4859 | 4865 | requires @\libconcept{sender_in}@<Sndr, Env>
|
4860 | 4866 | using value_types_of_t =
|
4861 | 4867 | @\exposid{gather-signatures}@<set_value_t, completion_signatures_of_t<Sndr, Env>, Tuple, Variant>;
|
4862 | 4868 |
|
4863 |
| - template<class Sndr, |
4864 |
| - class Env = empty_env, |
| 4869 | + template<class Sndr, class Env = env<>, |
4865 | 4870 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
4866 | 4871 | requires @\libconcept{sender_in}@<Sndr, Env>
|
4867 | 4872 | using error_types_of_t =
|
4868 | 4873 | @\exposid{gather-signatures}@<set_error_t, completion_signatures_of_t<Sndr, Env>,
|
4869 | 4874 | type_identity_t, Variant>;
|
4870 | 4875 |
|
4871 |
| - template<class Sndr, class Env = empty_env> |
| 4876 | + template<class Sndr, class Env = env<>> |
4872 | 4877 | requires @\libconcept{sender_in}@<Sndr, Env>
|
4873 | 4878 | constexpr bool sends_stopped =
|
4874 | 4879 | !@\libconcept{same_as}@<@\exposid{type-list}@<>,
|
|
4977 | 4982 | of all the \tcode{completion_signatures} specializations in the set
|
4978 | 4983 | \tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}.
|
4979 | 4984 |
|
| 4985 | +\rSec1[exec.envs]{Queryable uilities} |
| 4986 | + |
| 4987 | +\rSec2[exec.prop]{Class template \tcode{prop}} |
| 4988 | + |
| 4989 | +\begin{codeblock} |
| 4990 | +namespace std::execution { |
| 4991 | + template<class QueryTag, class ValueType> |
| 4992 | + struct @\libglobal{prop}@ { |
| 4993 | + QueryTag @\exposid{query_}@; // \expos |
| 4994 | + ValueType @\exposid{value_}@; // \expos |
| 4995 | + |
| 4996 | + constexpr const ValueType& query(QueryTag) const noexcept { |
| 4997 | + return @\exposid{value_}@; |
| 4998 | + } |
| 4999 | + }; |
| 5000 | + |
| 5001 | + template<class QueryTag, class ValueType> |
| 5002 | + prop(QueryTag, ValueType) -> prop<QueryTag, unwrap_reference_t<ValueType>>; |
| 5003 | +} |
| 5004 | +\end{codeblock} |
| 5005 | + |
| 5006 | +\pnum |
| 5007 | +Class template \tcode{prop} is for building a queryable object |
| 5008 | +from a query object and a value. |
| 5009 | + |
| 5010 | +\pnum |
| 5011 | +\mandates |
| 5012 | +\tcode{\exposconcept{callable}<QueryTag, \exposid{prop-like}<ValueType>>} |
| 5013 | +is modeled, |
| 5014 | +where \exposid{prop-like} is the following exposition-only class template: |
| 5015 | +\begin{codeblock} |
| 5016 | +template<class ValueType> |
| 5017 | +struct @\exposid{prop-like}@ { // \expos |
| 5018 | + const ValueType& query(auto) const noexcept; |
| 5019 | +}; |
| 5020 | +\end{codeblock} |
| 5021 | + |
| 5022 | +\pnum |
| 5023 | +\begin{example} |
| 5024 | +\begin{codeblock} |
| 5025 | +template<sender Sndr> |
| 5026 | +sender auto parameterize_work(Sndr sndr) { |
| 5027 | + // Make an environment such that \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}. |
| 5028 | + auto e = prop(get_allocator, my_alloc{}); |
| 5029 | + |
| 5030 | + // Parameterize the input sender so that it will use our custom execution environment. |
| 5031 | + return write_env(sndr, e); |
| 5032 | +} |
| 5033 | +\end{codeblock} |
| 5034 | +\end{example} |
| 5035 | + |
| 5036 | +\pnum |
| 5037 | +Specializations of \tcode{prop} are not assignable. |
| 5038 | + |
| 5039 | +\rSec2[exec.env]{Class template \tcode{env}} |
| 5040 | + |
| 5041 | +\begin{codeblock} |
| 5042 | +namespace std::execution { |
| 5043 | + template<@\exposconcept{queryable}@... Envs> |
| 5044 | + struct @\libglobal{env}@ { |
| 5045 | + Envs@$_0$@ @$\exposid{envs}_0$@; // \expos |
| 5046 | + Envs@$_1$@ @$\exposid{envs}_1$@; // \expos |
| 5047 | + @\vdots@ |
| 5048 | + Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos |
| 5049 | + |
| 5050 | + template<class QueryTag> |
| 5051 | + constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); |
| 5052 | + }; |
| 5053 | + |
| 5054 | + template<class... Envs> |
| 5055 | + env(Envs...) -> env<unwrap_reference_t<Envs>...>; |
| 5056 | +} |
| 5057 | +\end{codeblock} |
| 5058 | + |
| 5059 | +\pnum |
| 5060 | +The class template \tcode{env} is used to construct a queryable object |
| 5061 | +from several queryable objects. |
| 5062 | +Query invocations on the resulting object are resolved |
| 5063 | +by attempting to query each subobject in lexical order. |
| 5064 | + |
| 5065 | +\pnum |
| 5066 | +Specializations of \tcode{env} are not assignable. |
| 5067 | + |
| 5068 | +\pnum |
| 5069 | +It is unspecified |
| 5070 | +whether \tcode{env} supports initialization |
| 5071 | +using a parenthesized \grammarterm{expression-list}\iref{dcl.init}, |
| 5072 | +unless the \grammarterm{expression-list} consist of |
| 5073 | +a single element of type (possibly const) \tcode{env}. |
| 5074 | + |
| 5075 | +\pnum |
| 5076 | +\begin{example} |
| 5077 | +\begin{codeblock} |
| 5078 | +template<sender Sndr> |
| 5079 | +sender auto parameterize_work(Sndr sndr) { |
| 5080 | + // Make an environment such that: |
| 5081 | + // \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}} |
| 5082 | + // \tcode{get_scheduler(env)} returns a reference to a copy of \tcode{my_sched\{\}} |
| 5083 | + auto e = env{prop(get_allocator, my_alloc{}), |
| 5084 | + prop(get_scheduler, my_sched{})}; |
| 5085 | + |
| 5086 | + // Parameterize the input sender so that it will use our custom execution environment. |
| 5087 | + return write_env(sndr, e); |
| 5088 | +} |
| 5089 | +\end{codeblock} |
| 5090 | +\end{example} |
| 5091 | + |
| 5092 | +\indexlibrarymember{query}{env}% |
| 5093 | +\begin{itemdecl} |
| 5094 | +template<class QueryTag> |
| 5095 | +constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); |
| 5096 | +\end{itemdecl} |
| 5097 | + |
| 5098 | +\begin{itemdescr} |
| 5099 | +\pnum |
| 5100 | +Let \exposconcept{has-query} be the following exposition-only concept: |
| 5101 | +\begin{codeblock} |
| 5102 | +template<class Env, class QueryTag> |
| 5103 | + concept @\defexposconcept{has-query}@ = // \expos |
| 5104 | + requires (const Env& env) { |
| 5105 | + env.query(QueryTag()); |
| 5106 | + }; |
| 5107 | +\end{codeblock} |
| 5108 | + |
| 5109 | +\pnum |
| 5110 | +Let \exposid{fe} be the first element of |
| 5111 | +$\exposid{envs}_0$, $\exposid{envs}_1$, $\dotsc$, $\exposid{envs}_{n-1}$ |
| 5112 | +such that the expression \tcode{\exposid{fe}.query(q)} is well-formed. |
| 5113 | + |
| 5114 | +\pnum |
| 5115 | +\constraints |
| 5116 | +\tcode{(\exposconcept{has-query}<Envs, QueryTag> || ...)} is \tcode{true}. |
| 5117 | + |
| 5118 | +\pnum |
| 5119 | +\effects |
| 5120 | +Equivalent to: \tcode{return \exposid{fe}.query(q);} |
| 5121 | + |
| 5122 | +\pnum |
| 5123 | +\remarks |
| 5124 | +The expression in the \tcode{noexcept} clause is equivalent |
| 5125 | +to \tcode{noexcept(\exposid{fe}.query(q))}. |
| 5126 | +\end{itemdescr} |
| 5127 | + |
4980 | 5128 | \rSec1[exec.ctx]{Execution contexts}
|
4981 | 5129 |
|
4982 | 5130 | \rSec2[exec.run.loop]{\tcode{execution::run_loop}}
|
|
0 commit comments