Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
review feedback, fix sender_traits specification
  • Loading branch information
ericniebler committed Aug 26, 2021
commit fd6ebf9ae4222078437b7c03e8fb087955d866fb
9 changes: 5 additions & 4 deletions include/execution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ namespace std::execution {
using __single_or_void_t = __back_t<void, As...>;

template<class S>
using __single_sender_result_t =
using __single_sender_value_t =
typename sender_traits<remove_cvref_t<S>>
::template value_types<__single_or_void_t, __single_or_void_t>;

template<class S>
concept __single_typed_sender =
typed_sender<S> &&
requires { typename __single_sender_result_t<S>; };
requires { typename __single_sender_value_t<S>; };

/////////////////////////////////////////////////////////////////////////////
// [execution.op_state]
Expand Down Expand Up @@ -294,6 +294,7 @@ namespace std::execution {

// Pass through receiver queries
template<class... As, invocable<R&, As...> CPO>
requires (!__one_of<CPO, set_value_t, set_error_t, set_done_t>)
friend auto tag_invoke(CPO cpo, const promise_type& self, As&&... as)
noexcept(is_nothrow_invocable_v<CPO, R&, As...>)
-> invoke_result_t<CPO, R&, As...> {
Expand Down Expand Up @@ -480,11 +481,11 @@ namespace std::execution {

template <typename P_, typename S_>
struct __awaitable
: __awaitable_base<P_, __single_sender_result_t<__t<S_>>> {
: __awaitable_base<P_, __single_sender_value_t<__t<S_>>> {
private:
using Promise = __t<P_>;
using Sender = __t<S_>;
using Base = __awaitable_base<P_, __single_sender_result_t<Sender>>;
using Base = __awaitable_base<P_, __single_sender_value_t<Sender>>;
using __rec = typename Base::__rec;
connect_result_t<Sender, __rec> op_;
public:
Expand Down
12 changes: 6 additions & 6 deletions std_execution.bs
Original file line number Diff line number Diff line change
Expand Up @@ -2130,12 +2130,12 @@ enum class forward_progress_guarantee {
};
</pre>

5. If `sender_traits<S>::value_types<Tuple, Variant>` for some sender type `S` is well formed, it shall be a type `Variant<Tuple<Args0..., Args1..., ..., ArgsN...>>`, where the type packs `Args0` through `ArgsN` are the packs of types the sender `S` passes as
arguments to `execution::set_value` after a receiver object. If such sender `S` invokes `execution::set_value(r, args...)` for some receiver `r`, where `decltype(args)` is not one of the type packs `Args0` through `ArgsN`, the program is ill-formed with no
5. If `sender_traits<S>::value_types<Tuple, Variant>` for some sender type `S` is well formed, it shall be a type <code>Variant&lt;Tuple&lt;Args<sub>0</sub>...>, Tuple&lt;Args<sub>1</sub>...>, ..., Tuple&lt;Args<sub>N</sub>...>>></code>, where the type packs <code>Args<sub>0</sub></code> through <code>Args<sub>N</sub></code> are the packs of types the sender `S` passes as
arguments to `execution::set_value` after a receiver object. If such sender `S` invokes `execution::set_value(r, args...)` for some receiver `r`, where `decltype(args)` is not one of the type packs <code>Args<sub>0</sub></code> through <code>Args<sub>N</sub></code>, the program is ill-formed with no
diagnostic required.

6. If `sender_traits<S>::error_types<Variant>` for some sender type `S` is well formed, it shall be a type `Variant<E0, E1, ..., EN>`, where the types `E0` through `EN` are the types the sender `S` passes as arguments to `execution::set_error` after a receiver
object. If such sender `S` invokes `execution::set_error(r, e)` for some receiver `r`, where `decltype(e)` is not one of the types `E0` through `EN`, the program is ill-formed with no diagnostic required.
6. If `sender_traits<S>::error_types<Variant>` for some sender type `S` is well formed, it shall be a type <code>Variant&lt;E<sub>0</sub>, E<sub>1</sub>, ..., E<sub>N</sub>></code>, where the types <code>E<sub>0</sub></code> through <code>E<sub>N</sub></code> are the types the sender `S` passes as arguments to `execution::set_error` after a receiver
object. If such sender `S` invokes `execution::set_error(r, e)` for some receiver `r`, where `decltype(e)` is not one of the types <code>E<sub>0</sub></code> through <code>E<sub>N</sub></code>, the program is ill-formed with no diagnostic required.

7. If `sender_traits<S>::sends_done` is well formed and `false`, and such sender `S` invokes `execution::set_done(r)` for some receiver `r`, the program is ill-formed with no diagnostic required.

Expand Down Expand Up @@ -2166,7 +2166,7 @@ enum class forward_progress_guarantee {
}
</pre>

where <code><i>connect-awaitable</i></code> starts suspended, and:
where <code><i>connect-awaitable</i></code> suspends at the <i>initial suspends point</i> ([dcl.fct.def.coroutine]), and:

- <i>set-value-expr</i> first evaluates `co_await (S&&) s`, then suspends the coroutine and evaluates `execution::set_value((R&&) r)` if <code><i>await-result-type</i>&lt;S></code> is <code><i>cv</i> void</code>; otherwise, it evaluates `auto&& res = co_await (S&&) s`, then suspends the coroutine and evaluates `execution::set_value((R&&) r, (decltype(res)) res)`.

Expand All @@ -2180,7 +2180,7 @@ enum class forward_progress_guarantee {

- <code><i>operation-state-task</i></code> is a type that models `operation_state`. Its `execution::start` resumes the <code><i>connect-awaitable</i></code> coroutine, advancing it past the initial suspend point.

- Let `p` be an lvalue reference to the promise of the <code><i>connect-awaitable</i></code> coroutine and let `c` be any customization point object. Then `std::tag_invoke(c, p, as...)` is expression-equivalent to `std::tag_invoke(c, r, as...)` for any set of arguments `as...`.
- Let `p` be an lvalue reference to the promise of the <code><i>connect-awaitable</i></code> coroutine, let `b` be an lvalue reference to the receiver `r`, and let `c` be any customization point object excluding those of type `set_value_t`, `set_error_t` and `set_done_t`. Then `std::tag_invoke(c, p, as...)` is expression-equivalent to `std::tag_invoke(c, b, as...)` for any set of arguments `as...`.

The operand of the <i>requires-clause</i> of <code><i>connect-awaitable</i></code> is equivalent to `receiver_of<R>` if <code><i>await-result-type</i>&lt;S></code> is <code><i>cv</i> void</code>; otherwise, it is <code>receiver_of&lt;R, <i>await-result-type</i>&lt;S>></code>.

Expand Down