Skip to content

Commit 2cf73c8

Browse files
authored
Merge 2024-11 LWG Motion 19
P3325R5 A Utility for Creating Execution Environments
2 parents ef8c8ca + d58b6b1 commit 2cf73c8

File tree

1 file changed

+168
-20
lines changed

1 file changed

+168
-20
lines changed

source/exec.tex

Lines changed: 168 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -465,13 +465,20 @@
465465
template<class CPO>
466466
constexpr get_completion_scheduler_t<CPO> @\libglobal{get_completion_scheduler}@{};
467467

468-
struct @\libglobal{empty_env}@ {};
469468
struct @\libglobal{get_env_t}@ { @\unspec@ };
470469
inline constexpr get_env_t @\libglobal{get_env}@{};
471470

472471
template<class T>
473472
using @\libglobal{env_of_t}@ = decltype(get_env(declval<T>()));
474473

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+
475482
// \ref{exec.domain.default}, execution domains
476483
struct default_domain;
477484

@@ -513,7 +520,7 @@
513520
template<class Sndr>
514521
concept @\libconcept{sender}@ = @\seebelow@;
515522

516-
template<class Sndr, class Env = empty_env>
523+
template<class Sndr, class Env = env<>>
517524
concept @\libconcept{sender_in}@ = @\seebelow@;
518525

519526
template<class Sndr, class Rcvr>
@@ -526,7 +533,7 @@
526533
struct get_completion_signatures_t;
527534
inline constexpr get_completion_signatures_t get_completion_signatures {};
528535

529-
template<class Sndr, class Env = empty_env>
536+
template<class Sndr, class Env = env<>>
530537
requires @\libconcept{sender_in}@<Sndr, Env>
531538
using completion_signatures_of_t = @\exposid{call-result-t}@<get_completion_signatures_t, Sndr, Env>;
532539

@@ -536,18 +543,18 @@
536543
template<class... Ts>
537544
using @\exposidnc{variant-or-empty}@ = @\seebelownc@; // \expos
538545

539-
template<class Sndr, class Env = empty_env,
546+
template<class Sndr, class Env = env<>,
540547
template<class...> class Tuple = @\exposid{decayed-tuple}@,
541548
template<class...> class Variant = @\exposid{variant-or-empty}@>
542549
requires @\libconcept{sender_in}@<Sndr, Env>
543550
using value_types_of_t = @\seebelow@;
544551

545-
template<class Sndr, class Env = empty_env,
552+
template<class Sndr, class Env = env<>,
546553
template<class...> class Variant = @\exposid{variant-or-empty}@>
547554
requires @\libconcept{sender_in}@<Sndr, Env>
548555
using error_types_of_t = @\seebelow@;
549556

550-
template<class Sndr, class Env = empty_env>
557+
template<class Sndr, class Env = env<>>
551558
requires @\libconcept{sender_in}@<Sndr, Env>
552559
constexpr bool sends_stopped = @\seebelow@;
553560

@@ -661,7 +668,7 @@
661668

662669
template<
663670
@\libconcept{sender}@ Sndr,
664-
class Env = empty_env,
671+
class Env = env<>,
665672
@\exposconcept{valid-completion-signatures}@ AdditionalSignatures = completion_signatures<>,
666673
template<class...> class SetValue = @\seebelow@,
667674
template<class> class SetError = @\seebelow@,
@@ -833,7 +840,7 @@
833840
The type of the expression above satisfies
834841
\exposconcept{queryable}\iref{exec.queryable}.
835842
\item
836-
Otherwise, \tcode{empty_env\{\}}.
843+
Otherwise, \tcode{env<>\{\}}.
837844
\end{itemize}
838845

839846
\pnum
@@ -1785,7 +1792,7 @@
17851792
if constexpr (sizeof...(child) == 1)
17861793
return (@\exposid{FWD-ENV}@(get_env(child)), ...);
17871794
else
1788-
return empty_env();
1795+
return env<>();
17891796
}
17901797
\end{codeblock}
17911798

@@ -1929,7 +1936,7 @@
19291936
template<class Sndr>
19301937
concept @\defexposconcept{enable-sender}@ = // \expos
19311938
@\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}
19331940

19341941
template<class Sndr>
19351942
concept @\deflibconcept{sender}@ =
@@ -1940,7 +1947,7 @@
19401947
@\libconcept{move_constructible}@<remove_cvref_t<Sndr>> &&
19411948
@\libconcept{constructible_from}@<remove_cvref_t<Sndr>, Sndr>;
19421949

1943-
template<class Sndr, class Env = empty_env>
1950+
template<class Sndr, class Env = env<>>
19441951
concept @\deflibconcept{sender_in}@ =
19451952
@\libconcept{sender}@<Sndr> &&
19461953
@\exposconcept{queryable}@<Env> &&
@@ -1998,7 +2005,7 @@
19982005
value_types_of_t<Sndr, Env, @\exposid{value-signature}@, type_identity_t>);
19992006

20002007
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...>;
20022009
}
20032010
\end{codeblock}
20042011

@@ -2680,7 +2687,7 @@
26802687
\tcode{\exposid{FWD-ENV}(get_env(sndr))}\iref{exec.fwd.env}.
26812688
\item
26822689
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<>\{\}}.
26842691
\item
26852692
When a parent sender is connected to a receiver \tcode{rcvr},
26862693
any receiver used to connect a child sender has
@@ -3401,7 +3408,7 @@
34013408
\item
34023409
\tcode{\exposid{MAKE-ENV}(get_domain, get_domain(get_env(sndr)))}
34033410
\item
3404-
\tcode{(void(sndr), empty_env\{\})}
3411+
\tcode{(void(sndr), env<>\{\})}
34053412
\end{itemize}
34063413

34073414
\pnum
@@ -4114,7 +4121,7 @@
41144121
\begin{codeblock}
41154122
[](auto&&, auto&&... child) noexcept {
41164123
if constexpr (@\libconcept{same_as}@<CD, default_domain>) {
4117-
return empty_env();
4124+
return env<>();
41184125
} else {
41194126
return @\exposid{MAKE-ENV}@(get_domain, CD());
41204127
}
@@ -4852,23 +4859,21 @@
48524859
template<@\exposconcept{completion-signature}@... Fns>
48534860
struct completion_signatures {};
48544861

4855-
template<class Sndr,
4856-
class Env = empty_env,
4862+
template<class Sndr, class Env = env<>,
48574863
template<class...> class Tuple = @\exposid{decayed-tuple}@,
48584864
template<class...> class Variant = @\exposid{variant-or-empty}@>
48594865
requires @\libconcept{sender_in}@<Sndr, Env>
48604866
using value_types_of_t =
48614867
@\exposid{gather-signatures}@<set_value_t, completion_signatures_of_t<Sndr, Env>, Tuple, Variant>;
48624868

4863-
template<class Sndr,
4864-
class Env = empty_env,
4869+
template<class Sndr, class Env = env<>,
48654870
template<class...> class Variant = @\exposid{variant-or-empty}@>
48664871
requires @\libconcept{sender_in}@<Sndr, Env>
48674872
using error_types_of_t =
48684873
@\exposid{gather-signatures}@<set_error_t, completion_signatures_of_t<Sndr, Env>,
48694874
type_identity_t, Variant>;
48704875

4871-
template<class Sndr, class Env = empty_env>
4876+
template<class Sndr, class Env = env<>>
48724877
requires @\libconcept{sender_in}@<Sndr, Env>
48734878
constexpr bool sends_stopped =
48744879
!@\libconcept{same_as}@<@\exposid{type-list}@<>,
@@ -4977,6 +4982,149 @@
49774982
of all the \tcode{completion_signatures} specializations in the set
49784983
\tcode{AdditionalSignatures}, \tcode{Vs...}, \tcode{Es...}, \tcode{Ss}.
49794984

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+
49805128
\rSec1[exec.ctx]{Execution contexts}
49815129

49825130
\rSec2[exec.run.loop]{\tcode{execution::run_loop}}

0 commit comments

Comments
 (0)