This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4547. sender-awaitable needs a deduction guide

Section: 33.13.1 [exec.as.awaitable] Status: New Submitter: Eric Niebler Opened: 2026-03-19 Last modified: 2026-03-21

Priority: Not Prioritized

View other active issues in [exec.as.awaitable].

View all other issues in [exec.as.awaitable].

View all issues with New status.

Discussion:

33.13.1 [exec.as.awaitable] p2 has the following class declaration for the exposition-only sender-awaitable type:

template<class Sndr, class Promise>
class sender-awaitable {
  struct unit {};                                             // exposition only
  using value-type =                                          // exposition only
    single-sender-value-type<Sndr, env_of_t<Promise>>;
  using result-type =                                         // exposition only
    conditional_t<is_void_v<value-type>, unit, value-type>;
  struct awaitable-receiver;                                  // exposition only

  variant<monostate, result-type, exception_ptr> result{};    // exposition only
  connect_result_t<Sndr, awaitable-receiver> state;           // exposition only

public:
  sender-awaitable(Sndr&& sndr, Promise& p);
  static constexpr bool await_ready() noexcept { return false; }
  void await_suspend(coroutine_handle<Promise>) noexcept { start(state); }
  value-type await_resume();
};

In 33.13.1 [exec.as.awaitable] p2, CTAD is used to deduce the template parameters of sender-awaitable in the expressions sender-awaitable{adapted-expr, p} and sender-awaitable{expr, p}.

If decltype(expr) is a type Expr& (i.e., expr is an lvalue subexpression), then CTAD will deduce the type as sender-awaitable<Expr, Promise> and the expression sender-awaitable{expr, p} will be ill-formed because it is trying to bind an lvalue subexpression to an rvalue reference parameter.

The intention was that the template parameter Sndr would be deduced preserving the cv- and reference-qualification of the sender subexpression. In order to achieve that, we need to add a deduction guide.

Proposed resolution:

This wording is relative to N5032.

  1. Modify 33.13.1 [exec.as.awaitable] as indicated:

    -2- The type sender-awaitable<Sndr, Promise> is equivalent to:

    namespace std::execution {
      template<class Sndr, class Promise>
      class sender-awaitable {
        struct unit {};                                             // exposition only
        using value-type =                                          // exposition only
          single-sender-value-type<Sndr, env_of_t<Promise>>;
        using result-type =                                         // exposition only
          conditional_t<is_void_v<value-type>, unit, value-type>;
        struct awaitable-receiver;                                  // exposition only
      
        variant<monostate, result-type, exception_ptr> result{};    // exposition only
        connect_result_t<Sndr, awaitable-receiver> state;           // exposition only
      
      public:
        sender-awaitable(Sndr&& sndr, Promise& p);
        static constexpr bool await_ready() noexcept { return false; }
        void await_suspend(coroutine_handle<Promise>) noexcept { start(state); }
        value-type await_resume();
      };
      
      template<class Sndr, class Promise>
        sender-awaitable(Sndr&&, Promise&) -> sender-awaitable<Sndr, Promise>;
    }