Description
I was making my own coroutine task basic_task<Ret, Queries...>
which is an awaitable for promises that have an env that is queryable for all specified Queries...
The current spec defines the following two sender concepts
template<class Sndr>
concept enable-sender = // exposition only
is-sender<Sndr> ||
is-awaitable<Sndr, env-promise<empty_env>>; // [exec.awaitable]
template<class Sndr>
concept sender =
bool(enable-sender<remove_cvref_t<Sndr>>) &&
requires (const remove_cvref_t<Sndr>& sndr) {
{ get_env(sndr) } -> queryable;
} &&
move_constructible<remove_cvref_t<Sndr>> &&
constructible_from<remove_cvref_t<Sndr>, Sndr>;
template<class Sndr, class Env = empty_env>
concept sender_in =
sender<Sndr> &&
queryable<Env> &&
requires (Sndr&& sndr, Env&& env) {
{ get_completion_signatures(std::forward<Sndr>(sndr), std::forward<Env>(env)) }
-> valid-completion-signatures;
};
The current concepts require basic_task<Ret, Queries...>
to be awaitable in env-promise<empty_env>
which is too strict, IMHO. Instead we could require for sender_in
:
template<class Sndr, class Env = empty_env>
concept sender_in =
is-awaitable<Sndr, env-promise<Env>> ||
sender<Sndr> &&
queryable<Env> &&
requires (Sndr&& sndr, Env&& env) {
{ get_completion_signatures(std::forward<Sndr>(sndr), std::forward<Env>(env)) }
-> valid-completion-signatures;
};
There are some places where we mandate input to satisfy the sender concept. The most used one is for connect(sndr, rcvr)
expressions. The current spec states https://eel.is/c++draft/exec.snd#exec.connect-6
The expression connect(sndr, rcvr) is expression-equivalent to:
(6.1)
new_sndr.connect(rcvr) if that expression is well-formed.
Mandates: The type of the expression above satisfies operation_state.
(6.2)
Otherwise, connect-awaitable(new_sndr, rcvr).
Mandates:sender<Sndr>
&&receiver<Rcvr>
is true.
I would like to Mandate receiver<Rcvr> && sender_in<Sndr, env_of_t<Rcvr>>
Any thoughts?