Description
When writing a generic recursive sender transform, you need to ability to unpack an unknown sender S
and recursively transform the children.
For that, it can be useful to know the type of the environment that S
will use when connecting its child senders, which is why transform_env
exists.
For an environment E
and a sender S
with tag T
child C
, the expression default_domain().transform_env( S, E )
should return an environment E2
that is identical to the environment of the receiver that S
uses to connect C
.
default_domain().transform_env( S, E )
will first check whether T().transform_env( S, E )
is well-formed. If so, it will return that (e.g. when_all_t
has a transform_env
that adds a stop token to the environment).
If T().transform_env(S,E)
is not well-formed, what should default_domain::transform_env
do? At present, it returns E
unmodified.
But [exec.adapt.general] has this:
[unless otherwise specified, when] a parent sender is connected to a receiver
rcvr
, any receiver used to connect a child sender has an associated environment equal toFWD-ENV(get_env(rcvr))
.
So the correct thing for default_domain::transform_env
to do is to return FWD-ENV(get_env(rcvr))
.
Proposed resolution
Change [exec.domain.default] para 5 as follows:
template<sender Sndr, queryable Env>
constexpr queryable decltype(auto) transform_env(Sndr&& sndr, Env&& env) noexcept;
5. Let e be the expression
tag_of_t<Sndr>().transform_env(std::forward<Sndr>(sndr), std::forward<Env>(env))
- if that expression is well-formed; otherwise, static_cast<Env>(std::forward<Env>(env)).
+ if that expression is well-formed; otherwise, FWD-ENV(std::forward<Env>(env)).