|
466 | 466 | template<class CPO>
|
467 | 467 | constexpr get_completion_scheduler_t<CPO> @\libglobal{get_completion_scheduler}@{};
|
468 | 468 |
|
469 |
| - struct @\libglobal{empty_env}@ {}; |
470 | 469 | struct @\libglobal{get_env_t}@ { @\unspec@ };
|
471 | 470 | inline constexpr get_env_t @\libglobal{get_env}@{};
|
472 | 471 |
|
473 | 472 | template<class T>
|
474 | 473 | using @\libglobal{env_of_t}@ = decltype(get_env(declval<T>()));
|
475 | 474 |
|
| 475 | + // \ref{exec.prop}, class template \tcode{prop} |
| 476 | + template<class QueryTag, class ValueType> |
| 477 | + struct prop; |
| 478 | + |
| 479 | + // \ref{exec.env}, class template \tcode{env} |
| 480 | + template<@\exposconcept{queryable}@... Envs> |
| 481 | + struct env; |
| 482 | + |
476 | 483 | // \ref{exec.domain.default}, execution domains
|
477 | 484 | struct default_domain;
|
478 | 485 |
|
|
514 | 521 | template<class Sndr>
|
515 | 522 | concept @\libconcept{sender}@ = @\seebelow@;
|
516 | 523 |
|
517 |
| - template<class Sndr, class Env = empty_env> |
| 524 | + template<class Sndr, class Env = env<>> |
518 | 525 | concept @\libconcept{sender_in}@ = @\seebelow@;
|
519 | 526 |
|
520 | 527 | template<class Sndr, class Rcvr>
|
|
527 | 534 | struct get_completion_signatures_t;
|
528 | 535 | inline constexpr get_completion_signatures_t get_completion_signatures {};
|
529 | 536 |
|
530 |
| - template<class Sndr, class Env = empty_env> |
| 537 | + template<class Sndr, class Env = env<>> |
531 | 538 | requires @\libconcept{sender_in}@<Sndr, Env>
|
532 | 539 | using completion_signatures_of_t = @\exposid{call-result-t}@<get_completion_signatures_t, Sndr, Env>;
|
533 | 540 |
|
|
537 | 544 | template<class... Ts>
|
538 | 545 | using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos
|
539 | 546 |
|
540 |
| - template<class Sndr, class Env = empty_env, |
| 547 | + template<class Sndr, class Env = env<>, |
541 | 548 | template<class...> class Tuple = @\exposid{decayed-tuple}@,
|
542 | 549 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
543 | 550 | requires @\libconcept{sender_in}@<Sndr, Env>
|
544 | 551 | using value_types_of_t = @\seebelow@;
|
545 | 552 |
|
546 |
| - template<class Sndr, class Env = empty_env, |
| 553 | + template<class Sndr, class Env = env<>, |
547 | 554 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
548 | 555 | requires @\libconcept{sender_in}@<Sndr, Env>
|
549 | 556 | using error_types_of_t = @\seebelow@;
|
550 | 557 |
|
551 |
| - template<class Sndr, class Env = empty_env> |
| 558 | + template<class Sndr, class Env = env<>> |
552 | 559 | requires @\libconcept{sender_in}@<Sndr, Env>
|
553 | 560 | constexpr bool sends_stopped = @\seebelow@;
|
554 | 561 |
|
|
662 | 669 |
|
663 | 670 | template<
|
664 | 671 | @\libconcept{sender}@ Sndr,
|
665 |
| - class Env = empty_env, |
| 672 | + class Env = env<>, |
666 | 673 | @\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>,
|
667 | 674 | template<class...> class SetValue = @\seebelow@,
|
668 | 675 | template<class> class SetError = @\seebelow@,
|
|
834 | 841 | The type of the expression above satisfies
|
835 | 842 | \exposconcept{queryable}\iref{exec.queryable}.
|
836 | 843 | \item
|
837 |
| -Otherwise, \tcode{empty_env\{\}}. |
| 844 | +Otherwise, \tcode{env<>\{\}}. |
838 | 845 | \end{itemize}
|
839 | 846 |
|
840 | 847 | \pnum
|
|
1782 | 1789 | if constexpr (sizeof...(child) == 1)
|
1783 | 1790 | return (@\exposid{FWD-ENV}@(get_env(child)), ...);
|
1784 | 1791 | else
|
1785 |
| - return empty_env(); |
| 1792 | + return env<>(); |
1786 | 1793 | }
|
1787 | 1794 | \end{codeblock}
|
1788 | 1795 |
|
|
1913 | 1920 | template<class Sndr>
|
1914 | 1921 | concept @\defexposconcept{enable-sender}@ = // \expos
|
1915 | 1922 | @\exposconcept{is-sender}@<Sndr> ||
|
1916 |
| - @\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<empty_env>>; // \ref{exec.awaitable} |
| 1923 | + @\exposconcept{is-awaitable}@<Sndr, @\exposid{env-promise}@<env<>>>; // \ref{exec.awaitable} |
1917 | 1924 |
|
1918 | 1925 | template<class Sndr>
|
1919 | 1926 | concept @\deflibconcept{sender}@ =
|
|
1924 | 1931 | @\libconcept{move_constructible}@<remove_cvref_t<Sndr>> &&
|
1925 | 1932 | @\libconcept{constructible_from}@<remove_cvref_t<Sndr>, Sndr>;
|
1926 | 1933 |
|
1927 |
| - template<class Sndr, class Env = empty_env> |
| 1934 | + template<class Sndr, class Env = env<>> |
1928 | 1935 | concept @\deflibconcept{sender_in}@ =
|
1929 | 1936 | @\libconcept{sender}@<Sndr> &&
|
1930 | 1937 | @\exposconcept{queryable}@<Env> &&
|
|
1982 | 1989 | value_types_of_t<Sndr, Env, @\exposid{value-signature}@, type_identity_t>);
|
1983 | 1990 |
|
1984 | 1991 | template<class Sndr, class... Values>
|
1985 |
| - concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, empty_env, Values...>; |
| 1992 | + concept @\defexposconcept{sender-of}@ = @\exposconcept{sender-in-of}@<Sndr, env<>, Values...>; |
1986 | 1993 | }
|
1987 | 1994 | \end{codeblock}
|
1988 | 1995 |
|
|
2665 | 2672 | \tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}.
|
2666 | 2673 | \item
|
2667 | 2674 | A parent sender with more than one child sender has
|
2668 |
| -an associated attributes object equal to \tcode{empty_env\{\}}. |
| 2675 | +an associated attributes object equal to \tcode{env<>\{\}}. |
2669 | 2676 | \item
|
2670 | 2677 | When a parent sender is connected to a receiver \tcode{rcvr},
|
2671 | 2678 | any receiver used to connect a child sender has
|
|
3387 | 3394 | \item
|
3388 | 3395 | \tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))}
|
3389 | 3396 | \item
|
3390 |
| -\tcode{(void(sndr), empty_env\{\})} |
| 3397 | +\tcode{(void(sndr), env<>\{\})} |
3391 | 3398 | \end{itemize}
|
3392 | 3399 |
|
3393 | 3400 | \pnum
|
|
4088 | 4095 | \begin{codeblock}
|
4089 | 4096 | [](auto&&, auto&&... child) noexcept {
|
4090 | 4097 | if constexpr (@\libconcept{same_as}@<CD, default_domain>) {
|
4091 |
| - return empty_env(); |
| 4098 | + return env<>(); |
4092 | 4099 | } else {
|
4093 | 4100 | return @\exposid{MAKE-ENV}@(get_domain, CD());
|
4094 | 4101 | }
|
|
4816 | 4823 | template<@\exposconcept{completion-signature}@... Fns>
|
4817 | 4824 | struct completion_signatures {};
|
4818 | 4825 |
|
4819 |
| - template<class Sndr, |
4820 |
| - class Env = empty_env, |
| 4826 | + template<class Sndr, class Env = env<>, |
4821 | 4827 | template<class...> class Tuple = @\exposid{decayed-tuple}@,
|
4822 | 4828 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
4823 | 4829 | requires @\libconcept{sender_in}@<Sndr, Env>
|
4824 | 4830 | using value_types_of_t =
|
4825 | 4831 | @\exposid{gather-signatures}@<set_value_t, completion_signatures_of_t<Sndr, Env>, Tuple, Variant>;
|
4826 | 4832 |
|
4827 |
| - template<class Sndr, |
4828 |
| - class Env = empty_env, |
| 4833 | + template<class Sndr, class Env = env<>, |
4829 | 4834 | template<class...> class Variant = @\exposid{variant-or-empty}@>
|
4830 | 4835 | requires @\libconcept{sender_in}@<Sndr, Env>
|
4831 | 4836 | using error_types_of_t =
|
4832 | 4837 | @\exposid{gather-signatures}@<set_error_t, completion_signatures_of_t<Sndr, Env>,
|
4833 | 4838 | type_identity_t, Variant>;
|
4834 | 4839 |
|
4835 |
| - template<class Sndr, class Env = empty_env> |
| 4840 | + template<class Sndr, class Env = env<>> |
4836 | 4841 | requires @\libconcept{sender_in}@<Sndr, Env>
|
4837 | 4842 | constexpr bool sends_stopped =
|
4838 | 4843 | !@\libconcept{same_as}@<@\exposid{type-list}@<>,
|
|
4941 | 4946 | of all the \tcode{completion_signatures} specializations in the set
|
4942 | 4947 | \tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}.
|
4943 | 4948 |
|
| 4949 | +\rSec1[exec.envs]{Queryable uilities} |
| 4950 | + |
| 4951 | +\rSec2[exec.prop]{Class template \tcode{prop}} |
| 4952 | + |
| 4953 | +\begin{codeblock} |
| 4954 | +namespace std::execution { |
| 4955 | + template<class QueryTag, class ValueType> |
| 4956 | + struct @\libglobal{prop}@ { |
| 4957 | + QueryTag @\exposid{query_}@; // \expos |
| 4958 | + ValueType @\exposid{value_}@; // \expos |
| 4959 | + |
| 4960 | + constexpr const ValueType& query(QueryTag) const noexcept { |
| 4961 | + return @\exposid{value_}@; |
| 4962 | + } |
| 4963 | + }; |
| 4964 | + |
| 4965 | + template<class QueryTag, class ValueType> |
| 4966 | + prop(QueryTag, ValueType) -> prop<QueryTag, unwrap_reference_t<ValueType>>; |
| 4967 | +} |
| 4968 | +\end{codeblock} |
| 4969 | + |
| 4970 | +\pnum |
| 4971 | +Class template \tcode{prop} is for building a queryable object |
| 4972 | +from a query object and a value. |
| 4973 | + |
| 4974 | +\pnum |
| 4975 | +\mandates |
| 4976 | +\tcode{\exposconcept{callable}<QueryTag, \exposid{prop-like}<ValueType>>} |
| 4977 | +is modeled, |
| 4978 | +where \exposid{prop-like} is the following exposition-only class template: |
| 4979 | +\begin{codeblock} |
| 4980 | +template<class ValueType> |
| 4981 | +struct @\exposid{prop-like}@ { // \expos |
| 4982 | + const ValueType& query(auto) const noexcept; |
| 4983 | +}; |
| 4984 | +\end{codeblock} |
| 4985 | + |
| 4986 | +\pnum |
| 4987 | +\begin{example} |
| 4988 | +\begin{codeblock} |
| 4989 | +template<sender Sndr> |
| 4990 | +sender auto parameterize_work(Sndr sndr) { |
| 4991 | + // Make an environment such that \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}}. |
| 4992 | + auto e = prop(get_allocator, my_alloc{}); |
| 4993 | + |
| 4994 | + // Parameterize the input sender so that it will use our custom execution environment. |
| 4995 | + return write_env(sndr, e); |
| 4996 | +} |
| 4997 | +\end{codeblock} |
| 4998 | +\end{example} |
| 4999 | + |
| 5000 | +\pnum |
| 5001 | +Specializations of \tcode{prop} are not assignable. |
| 5002 | + |
| 5003 | +\rSec2[exec.env]{Class template \tcode{env}} |
| 5004 | + |
| 5005 | +\begin{codeblock} |
| 5006 | +namespace std::execution { |
| 5007 | + template<@\exposconcept{queryable}@... Envs> |
| 5008 | + struct @\libglobal{env}@ { |
| 5009 | + Envs@$_0$@ @$\exposid{envs}_0$@; // \expos |
| 5010 | + Envs@$_1$@ @$\exposid{envs}_1$@; // \expos |
| 5011 | + @\vdots@ |
| 5012 | + Envs@$_{n-1}$@ @$\exposid{envs}_{n-1}$@; // \expos |
| 5013 | + |
| 5014 | + template<class QueryTag> |
| 5015 | + constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); |
| 5016 | + }; |
| 5017 | + |
| 5018 | + template<class... Envs> |
| 5019 | + env(Envs...) -> env<unwrap_reference_t<Envs>...>; |
| 5020 | +} |
| 5021 | +\end{codeblock} |
| 5022 | + |
| 5023 | +\pnum |
| 5024 | +The class template \tcode{env} is used to construct a queryable object |
| 5025 | +from several queryable objects. |
| 5026 | +Query invocations on the resulting object are resolved |
| 5027 | +by attempting to query each subobject in lexical order. |
| 5028 | + |
| 5029 | +\pnum |
| 5030 | +Specializations of \tcode{env} are not assignable. |
| 5031 | + |
| 5032 | +\pnum |
| 5033 | +It is unspecified |
| 5034 | +whether \tcode{env} supports initialization |
| 5035 | +using a parenthesized \grammarterm{expression-list}\iref{dcl.init}, |
| 5036 | +unless the \grammarterm{expression-list} consist of |
| 5037 | +a single element of type (possibly const) \tcode{env}. |
| 5038 | + |
| 5039 | +\pnum |
| 5040 | +\begin{example} |
| 5041 | +\begin{codeblock} |
| 5042 | +template<sender Sndr> |
| 5043 | +sender auto parameterize_work(Sndr sndr) { |
| 5044 | + // Make an environment such that: |
| 5045 | + // \tcode{get_allocator(env)} returns a reference to a copy of \tcode{my_alloc\{\}} |
| 5046 | + // \tcode{get_scheduler(env)} returns a reference to a copy of \tcode{my_sched\{\}} |
| 5047 | + auto e = env{prop(get_allocator, my_alloc{}), |
| 5048 | + prop(get_scheduler, my_sched{})}; |
| 5049 | + |
| 5050 | + // Parameterize the input sender so that it will use our custom execution environment. |
| 5051 | + return write_env(sndr, e); |
| 5052 | +} |
| 5053 | +\end{codeblock} |
| 5054 | +\end{example} |
| 5055 | + |
| 5056 | +\indexlibrarymember{query}{env}% |
| 5057 | +\begin{itemdecl} |
| 5058 | +template<class QueryTag> |
| 5059 | +constexpr decltype(auto) query(QueryTag q) const noexcept(@\seebelow@); |
| 5060 | +\end{itemdecl} |
| 5061 | + |
| 5062 | +\begin{itemdescr} |
| 5063 | +\pnum |
| 5064 | +Let \exposconcept{has-query} be the following exposition-only concept: |
| 5065 | +\begin{codeblock} |
| 5066 | +template<class Env, class QueryTag> |
| 5067 | + concept @\defexposconcept{has-query}@ = // \expos |
| 5068 | + requires (const Env& env) { |
| 5069 | + env.query(QueryTag()); |
| 5070 | + }; |
| 5071 | +\end{codeblock} |
| 5072 | + |
| 5073 | +\pnum |
| 5074 | +Let \exposid{fe} be the first element of |
| 5075 | +$\exposid{envs}_0$, $\exposid{envs}_1$, $\dotsc$, $\exposid{envs}_{n-1}$ |
| 5076 | +such that the expression \tcode{\exposid{fe}.query(q)} is well-formed. |
| 5077 | + |
| 5078 | +\pnum |
| 5079 | +\constraints |
| 5080 | +\tcode{(\exposconcept{has-query}<Envs, QueryTag> || ...)} is \tcode{true}. |
| 5081 | + |
| 5082 | +\pnum |
| 5083 | +\effects |
| 5084 | +Equivalent to: \tcode{return \exposid{fe}.query(q);} |
| 5085 | + |
| 5086 | +\pnum |
| 5087 | +\remarks |
| 5088 | +The expression in the \tcode{noexcept} clause is equivalent |
| 5089 | +to \tcode{noexcept(\exposid{fe}.query(q))}. |
| 5090 | +\end{itemdescr} |
| 5091 | + |
4944 | 5092 | \rSec1[exec.ctx]{Execution contexts}
|
4945 | 5093 |
|
4946 | 5094 | \rSec2[exec.run.loop]{\tcode{execution::run_loop}}
|
|
0 commit comments