Title
`transform_sender` comparing types ignoring cv-qualifiers doesn't take into account differences in value category
Status
new
Section
[exec.snd.transform]
Submitter
Lewis Baker

Created on 2025-08-28.00:00:00 last changed 2 days ago

Messages

Date: 2025-09-15.10:37:43

Proposed resolution:

This wording is relative to N5014.

  1. Modify [exec.snd.transform] as indicated:

    namespace std::execution {
      template<class Domain, sender Sndr, queryable... Env>
        requires (sizeof...(Env) <= 1)
      constexpr sender decltype(auto) transform_sender(Domain dom, Sndr&& sndr, const Env&... env)
        noexcept(see below);
    }
    

    -1- Let transformed-sndr be the expression

    dom.transform_sender(std::forward<Sndr>(sndr), env...)
    

    if that expression is well-formed; otherwise,

    default_domain().transform_sender(std::forward<Sndr>(sndr), env...)
    

    Let final-sndr be the expression transformed-sndr if transformed-sndr and sndr have the same decayed type ignoring cv-qualifiers; otherwise, it is the expression transform_sender(dom, transformed-sndr, env...).

Date: 2025-08-28.00:00:00

In [exec.snd.transform] p1, the specification for `transform_sender()` states:

Let transformed-sndr be the expression

dom.transform_sender(std::forward<Sndr>(sndr), env...)

if that expression is well-formed; otherwise,

default_domain().transform_sender(std::forward<Sndr>(sndr), env...)

Let final-sndr be the expression transformed-sndr if transformed-sndr and sndr have the same type ignoring cv-qualifiers; otherwise, it is the expression transform_sender(dom, transformed-sndr, env...).

However, the use of the phrase "have the same type ignoring cv-qualifiers" asks to compare the types without `const` or `volatile` qualifiers, but doesn't take into account differences in value category of the types of these expressions.

For example `sndr` might have type T&& and transformed-sndr might return a new prvalue of type `T`.

My interpretation of the current wording is that I should apply the test same_as<remove_cv_t<decltype(sndr)>, remove_cv_t<decltype(transformed-sndr)>>.

However, `remove_cv_t` does not remove reference-qualifiers from a type Sndr&& (which in the above example, is the type of `sndr`), and thus would compare as different to a transform-sndr type of `Sndr`.

I believe the intention is that this should instead use same_as<remove_cvref_t<decltype(sndr)>, remove_cvref_t<decltype(transformed-sndr)>>. For example, the implementation in NVIDIA's stdexec repository uses same_as<decay_t<T>, decay_t<U>> for this check.

The wording should be modified to use a phrase that removes both reference and cv-qualifiers when comparing types.

History
Date User Action Args
2025-09-15 10:37:43adminsetmessages: + msg15044
2025-08-28 00:00:00admincreate