diff --git a/execution.html b/execution.html index 97c8ad2..880aa51 100644 --- a/execution.html +++ b/execution.html @@ -2246,7 +2246,7 @@

D2300R8
std::execution

-

Draft Proposal,

+

Draft Proposal,

Authors: @@ -3655,6 +3655,11 @@

2.1. Add a requirement on queryable objects that if tag_invoke(query, env, args...) is well-formed, then query(env, args...) is expression-equivalent to it. This is necessary to properly specify how to join two environments in the presence of queries that have defaults.

+
  • +

    The sender_in<Sndr, Env> concept requires that E satisfies queryable.

    +
  • +

    The exposition-only class template basic-sender is greatly +enhanced, and the sender algorithms are respecified in term of it.

    2.2. R7

    The changes since R6 are as follows:

    @@ -6119,20 +6124,16 @@

  • -

    A completion operation has an associated completion signature. A completion signature is a function type that describes a -completion operation. An asychronous operation has a finite set of possible -completion signatures corresponding to the completion operations that the -asynchronous operation potentially evaluates ([basic.def.odr]). The -completion signature’s return type is the completion tag associated with the -completion function that executes the completion operation. The completion -signature’s parameter types are the (possibly cv- and reference-qualified) -types of the asynchronous operation’s result datums, modulo rvalue reference -qualification (see MATCHING-SIG in [exec.general]). -[Example: For subexpressions x and y, the completion signature -corresponding to the completion operation set_value(std::move(rcvr), x, y) is set_value_t(decltype((x)), decltype((y))). -- end example] Together, +

    A completion signature is a function type that +describes a completion operation. An asychronous operation has a finite set +of possible completion signatures corresponding to the completion operations +that the asynchronous operation potentially evaluates ([basic.def.odr]). For +a completion function set, receiver rcvr, and pack of arguments args, +let c be the completion operation set(rcvr, args...), and let F be the function type decltype(auto(set))(decltype((args))...). +A completion signature S is associated with c if and only if MATCHING-SIG(S, F) is true ([exec.general]). Together, a sender type and an environment type E determine the set of completion signatures of an asynchronous operation that results from connecting the -sender with a receiver whose environment has type E. The type of the receiver does not affect an asychronous +sender with a receiver that has an environment of type E. The type of the receiver does not affect an asychronous operation’s completion signatures, only the type of the receiver’s environment.

  • @@ -6326,9 +6327,11 @@

    using tag_of_t = see below; // [exec.snd.transform], sender transformations - template<class Domain, sender Sender, class... Env> - requires (sizeof...(Env) <= 1) - constexpr sender decltype(auto) transform_sender(Domain dom, Sender&& sndr, const Env&... env); + template<class Domain, sender Sender> + constexpr sender decltype(auto) transform_sender(Domain dom, Sender&& sndrv); + + template<class Domain, sender Sender, class Env> + constexpr sender decltype(auto) transform_sender(Domain dom, Sender&& sndr, const Env& env); template<class Domain, sender Sender, class Env> constexpr decltype(auto) transform_env(Domain dom, Sender&& sndr, Env&& env) noexcept; @@ -6348,7 +6351,7 @@

    using connect_result_t = decltype(connect(declval<S>(), declval<R>())); // [exec.factories], sender factories - namespace senders-factories { // exposition only + namespace sender-factories { // exposition only struct just_t; struct just_error_t; struct just_stopped_t; @@ -6357,7 +6360,7 @@

    inline constexpr just just{}; inline constexpr just_error_t just_error{}; inline constexpr just_stopped_t just_stopped{}; - using senders-factories::schedule_t; + using sender-factories::schedule_t; inline constexpr schedule_t schedule{}; inline constexpr unspecified read{}; @@ -6907,23 +6910,21 @@

    sender concept ([async.ops]).

  • Subclauses [exec.factories] and [exec.adapt] define customizable algorithms -that return senders. Each algorithm has a default implementation specified -herein. Let sndr be the result of an invocation of such an algorithm or an -object equal to such ([concepts.equality]), and let Sndr be decltype((sndr)). Let Env be the type of an environment env such that sender_in<Sndr, Env> is true, and let rcvr be a receiver whose -associated environment is Env. For the default implementation of the +that return senders. Each algorithm has a default implementation. Let sndr be the result of an invocation of such an algorithm or an object equal to +such ([concepts.equality]), and let Sndr be decltype((sndr)). Let rcvr be a receiver with associated environment env of type Env such that sender_in<Sndr, Env> is true. For the default implementation of the algorithm that produced sndr, connecting sndr to rcvr and starting the resulting operation state ([async.ops]) necessarily results in the potential -evaluation ([intro.execution]) of a set of completion operations whose first +evaluation ([basic.def.odr]) of a set of completion operations whose first argument is a subexpression equal to rcvr. Let Sigs be a pack of completion signatures corresponding to this set of completion operations. Then the type of the expression get_completion_signatures(sndr, env) is a specialization of the class template completion_signatures, ([exec.utils.cmplsigs]) the set of whose template arguments is Sigs. If a user-provided implementation of the algorithm that produced sndr is -selected instead of the default, the set of completion signatures denoted by -the return type of get_completion_signatures(sndr, env) shall be a -superset of Sigs, with any additional completion signatures corresponding -to error or stopped completion operations.

    +selected instead of the default, any completion signature that is in the set +of types denoted by completion_signatures_of_t<Sndr, Env> and that is not +part of Sigs shall correspond to error or stopped completion operations, +unless otherwise specified.

  • This subclause makes use of the following exposition-only entities.

      @@ -7034,7 +7035,7 @@

      template<class... T> -struct tuple-like { +struct product-type { T0 t0; // exposition only T1 t1; // exposition only ... @@ -7043,7 +7044,7 @@

      An expression of type tuple-like is usable as the initializer +

      An expression of type product-type is usable as the initializer of a structured binding declaration [dcl.struct.bind].

    1. @@ -7115,8 +7116,8 @@

      default-impls::start is initialized with a callable object equal to the following lambda:

      -
      [](auto& state, auto& rcvr, auto&... ops) noexcept -> completion_signatures<> {
      +
      [](auto& state, auto& rcvr, auto&... ops) noexcept -> void {
         (execution::start(ops), ...);
      -  return {};
       }
       
    2. @@ -7227,24 +7230,20 @@

      []<class Index, class Rcvr, class Tag, class... Args>( Index, auto& state, Rcvr& rcvr, Tag, Args&&... args) noexcept - -> completion_signatures<Tag(Args...)> - requires callable<Tag, Rcvr, Args...> { + -> void requires callable<Tag, Rcvr, Args...> { // Mandates: Index::value == 0 - tag(std::move(rcvr), std::forward<Args>(args)...); - return {}; + Tag()(std::move(rcvr), std::forward<Args>(args)...); }

    3. -

      The return type of basic-sender’s customization of get_completion_signatures is computed as follows.

      -
        -
      1. -

        Let Env be the type of an environment, let the type Sndr be - the (possibly cv- and ref-qualified) type of a specialization - of basic-sender, and let Childi be the type of the i-th child sender of Sndr, with the same - cv- and ref-qualifications as Sndr.

        -
      2. -

        Let ChildEnvi be the type

        -
      +

      For a subexpression sndr let Sndr be decltype((sndr)). Let rcvr be a receiver that has an associated environment of type Env such that sender_in<Sndr, Env> is true. completion-signatures-for<Sndr, Env> denotes +a specialization of completion_signatures, the set of whose +template arguments correspond to the set of completion operations +that are potentially evaluated as a result of calling start on the +operation state that results from connecting sndr and rcvr. When sender_in<Sndr, Env> is false, the type denoted by completion-signatures-for<Sndr, Env>, if any, +is not a specialization of completion_signatures. When sender_in<Sndr, Env> is false, +implementations are encouraged to use the type denoted by completion-signatures-for<Sndr, Env> to +communicate to users why.

    @@ -7273,7 +7272,6 @@

    enable_sender<remove_cvref_t<S>> && requires (const remove_cvref_t<S>& s) { { get_env(s) } -> queryable; - completion-domain(s); } && move_constructible<remove_cvref_t<S>> && // rvalues are movable, and constructible_from<remove_cvref_t<S>, S>; // lvalues are copyable @@ -7281,6 +7279,7 @@

    template<class S, class E = empty_env> concept sender_in = sender<S> && + queryable<E> && requires (S&& s, E&& e) { { get_completion_signatures(std::forward<S>(s), std::forward<E>(e)) } -> valid-completion-signatures; @@ -7296,11 +7295,11 @@

  • Given a subexpression sndr, let Sndr be decltype((sndr)), let Env be -the type of an environment, and let rcvr be a receiver whose associated -environment is Env. A completion operation is a permissible completion for Sndr and Env if its -completion signature appears in the argument list of the specialization of completion_signatures denoted by completion_signatures_of_t<Sndr, Env>. Sndr and Env model sender_to<Sndr, Env> if connecting sndr to rcvr and starting the resulting operation state does not cause the potential -evaluation of any completion operation on rcvr that is not a permissible -completion for Sndr and Env.

    +the type of an environment, and let rcvr be a receiver with an associated +environment Env. A completion operation is a permissible completion for Sndr and Env if its +completion signature appears in the argument list of the specialization of completion_signatures denoted by completion_signatures_of_t<Sndr, Env>. Sndr and Env model sender_in<Sndr, Env> if all the completion +operations that are potentially evaluated by connecting sndr to rcvr and +starting the resulting operation state are permissible completions for Sndr and Env.

  • A type Sigs satisfies and models the exposition-only concept valid-completion-signatures if it names a specialization of the completion_signatures class template.

    @@ -7443,11 +7442,13 @@

    11.9.4. execution::default_domain [exec.domain.default]

    struct default_domain {
    -  template <sender Sender, class... Env>
    -      requires (sizeof...(Env) <= 1)
    -    static constexpr sender decltype(auto) transform_sender(Sender&& sndr, const Env&... env) noexcept(see below);
    +  template <sender Sender>
    +    static constexpr sender decltype(auto) transform_sender(Sender&& sndr) noexcept(see below);
    +
    +  template <sender Sender, queryable Env>
    +    static constexpr sender decltype(auto) transform_sender(Sender&& sndr, const Env& env) noexcept(see below);
     
    -  template <sender Sender, class Env>
    +  template <sender Sender, queryable Env>
         static constexpr decltype(auto) transform_env(Sender&& sndr, Env&& env) noexcept;
     
       template<class Tag, sender Sender, class... Args>
    @@ -7455,20 +7456,31 @@ 

    11.9.4.1. Static members [exec.domain.default.statics]

    -
    template <sender Sender, class... Env>
    -    requires (sizeof...(Env) <= 1)
    -  constexpr sender decltype(auto) default_domain::transform_sender(Sender&& sndr, const Env&... env) noexcept(see below);
    +
    template <sender Sender>
    +  constexpr sender decltype(auto) default_domain::transform_sender(Sender&& sndr) noexcept(see below);
     
    1. -

      Returns: tag_of_t<Sender>().transform_sender(std::forward<Sender>(sndr), env...) if that expression is well-formed; otherwise, std::forward<Sender>(sndr).

      +

      Returns: tag_of_t<Sender>().transform_sender(std::forward<Sender>(sndr)) if that expression is well-formed; otherwise, std::forward<Sender>(sndr).

    2. Remarks: The exception specification is equivalent to:

      -
      noexcept(tag_of_t<Sender>().transform_sender(std::forward<Sender>(sndr), env...))
      +
      noexcept(tag_of_t<Sender>().transform_sender(std::forward<Sender>(sndr)))
       

      if that expression is well-formed; otherwise, true;

    -
    template <sender Sender, class Env>
    +
    template <sender Sender, queryable Env>
    +  constexpr sender decltype(auto) default_domain::transform_sender(Sender&& sndr, const Env& env) noexcept(see below);
    +
    +
      +
    1. +

      Returns: tag_of_t<Sender>().transform_sender(std::forward<Sender>(sndr), env) if that expression is well-formed; otherwise, std::forward<Sender>(sndr).

      +
    2. +

      Remarks: The exception specification is equivalent to:

      +
      noexcept(tag_of_t<Sender>().transform_sender(std::forward<Sender>(sndr), env))
      +
      +

      if that expression is well-formed; otherwise, true;

      +
    +
    template <sender Sender, queryable Env>
       constexpr decltype(auto) default_domain::transform_env(Sender&& sndr, Env&& env) noexcept;
     
      @@ -7490,16 +7502,17 @@
      11.9.5. execution::transform_sender [exec.snd.transform]
      -
      template<class Domain, sender Sender, class... Env>
      -    requires (sizeof...(Env) <= 1)
      -  constexpr sender decltype(auto) transform_sender(Domain dom, Sender&& sndr, const Env&... env);
      +
      template<class Domain, sender Sender>
      +  constexpr sender decltype(auto) transform_sender(Domain dom, Sender&& sndr);
      +
      +template<class Domain, sender Sender, queryable Env>
      +  constexpr sender decltype(auto) transform_sender(Domain dom, Sender&& sndr, const Env& env);
       
      1. -

        Returns: Let s2 be the expression dom.transform_sender(std::forward<Sender>(sndr), env...) if that - expression is well-formed; otherwise, default_domain().transform_sender(std::forward<Sender>(sndr), env...). - If s2 and sndr have the same type ignoring _cv_ qualifiers, - returns s2; otherwise, transform_sender(dom, s2, env...).

        +

        Returns: Let ENV be a parameter pack consisting of + the single expression env for the second overload and an empty pack for + the first. Let s2 be the expression dom.transform_sender(std::forward<Sender>(sndr), ENV...) if that expression is well-formed; otherwise, default_domain().transform_sender(std::forward<Sender>(sndr), ENV...). If s2 and sndr have the same type ignoring cv qualifiers, returns s2; otherwise, transform_sender(dom, s2, ENV...).

      template<class Domain, sender Sender, class Env>
         constexpr decltype(auto) transform_env(Domain dom, Sender&& sndr, Env&& env) noexcept;
      @@ -7746,7 +7759,7 @@ 
      just-sender<Tag, Ts...> behave as do -expressions of type basic-sender<Tag, tuple-like<Ts...>>.

      +expressions of type basic-sender<Tag, product-type<Ts...>>.

    11.9.9.3. execution::read [exec.read]
      @@ -7988,8 +8001,8 @@
      This causes the transfer(s, sch) sender to become schedule_from(sch, s) when it is connected with a receiver whose -execution domain does not customize transfer.

      +

      This causes the transfer(s, sch) sender to become schedule_from(sch, s) when it is connected with a receiver with an +execution domain that does not customize transfer.

    11.9.10.5. execution::schedule_from [exec.schedule.from]
      @@ -8075,7 +8088,7 @@
      impls-for ([exec.snd.general]) is specialized for each of then_t, upon_error_t, and upon_stopped_t as follows:

      template<>
      -struct impls-for<then-cpo> : default-impls {
      +struct impls-for<decltype(auto(then-cpo))> : default-impls {
         static constexpr auto complete =
           []<class Tag, class... Args>(auto, auto& fn, auto& rcvr, Tag, Args&&... args) noexcept -> void {
             if constexpr (same_as<Tag, set-cpo>) {
      @@ -8084,7 +8097,7 @@ 
      s, shape, and f, let S be decltype((s)), Shape be decltype((shape)), and F be decltype((f)). If S does not satisfy sender or Shape does not satisfy integral, bulk is ill-formed. Otherwise, the expression bulk(s, shape, f) is expression-equivalent to:

      transform_sender(
         get-domain-early(s),
      -  make-bulk-sender(tuple-like{shape, f}, s));
      +  make-bulk-sender(product-type{shape, f}, s));
       

      where make-bulk-sender(t, s) is expression-equivalent to make-sender(bulk, t, s) for a subexpression t and returns a sender object s2 that behaves as follows:

      @@ -8478,7 +8491,7 @@
      This causes the when_all_with_variant(s...) sender to become when_all(into_variant(s)...) when it is connected with a -receiver whose execution domain does not customize when_all_with_variant.

      +receiver with an execution domain that does not customize when_all_with_variant.

    1. Given a pack of subexpressions s..., let S be an object returned from when_all(s...) or when_all_with_variant(s...) or a copy of such, and let E be the environment object returned from get_env(S). Given a query object Q, tag_invoke(Q, E) is expression-equivalent to get-domain-early(s0) when Q is get_domain; otherwise, it is ill-formed.