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 to FWD-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)).
When writing a generic recursive sender transform, you need to ability to unpack an unknown sender
Sand recursively transform the children.For that, it can be useful to know the type of the environment that
Swill use when connecting its child senders, which is whytransform_envexists.For an environment
Eand a senderSwith tagTchildC, the expressiondefault_domain().transform_env( S, E )should return an environmentE2that is identical to the environment of the receiver thatSuses to connectC.default_domain().transform_env( S, E )will first check whetherT().transform_env( S, E )is well-formed. If so, it will return that (e.g.when_all_thas atransform_envthat adds a stop token to the environment).If
T().transform_env(S,E)is not well-formed, what shoulddefault_domain::transform_envdo? At present, it returnsEunmodified.But [exec.adapt.general] has this:
So the correct thing for
default_domain::transform_envto do is to returnFWD-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)).