Files
cppdraft_translate/cppdraft/exec/connect.md
2025-10-25 03:02:53 +03:00

4.9 KiB
Raw Blame History

[exec.connect]

33 Execution control library [exec]

33.9 Senders [exec.snd]

33.9.10 execution::connect [exec.connect]

1

#

connect connects ([exec.async.ops]) a sender with a receiver.

2

#

The name connect denotes a customization point object.

For subexpressions sndr and rcvr, let Sndr be decltype((sndr)) andRcvr be decltype((rcvr)), let new_sndr be the expressiontransform_sender(decltype(get-domain-late(sndr, get_env(rcvr))){}, sndr, get_env(rcvr)) and let DS and DR bedecay_t<decltype((new_sndr))> and decay_t, respectively.

3

#

Let connect-awaitable-promise be the following exposition-only class:

namespace std::execution {struct connect-awaitable-promise : with-await-transform<connect-awaitable-promise> {connect-awaitable-promise(DS&, DR& rcvr) noexcept : rcvr(rcvr) {} suspend_always initial_suspend() noexcept { return {}; }noreturn suspend_always final_suspend() noexcept { terminate(); }noreturn void unhandled_exception() noexcept { terminate(); }noreturn void return_void() noexcept { terminate(); } coroutine_handle<> unhandled_stopped() noexcept { set_stopped(std::move(rcvr)); return noop_coroutine(); }operation-state-task get_return_object() noexcept {return operation-state-task{ coroutine_handle<connect-awaitable-promise>::from_promise(*this)}; } env_of_t get_env() const noexcept {return execution::get_env(rcvr); }private: DR& rcvr; // exposition only};}

4

#

Let operation-state-task be the following exposition-only class:namespace std::execution {struct operation-state-task { // exposition onlyusing operation_state_concept = operation_state_t; using promise_type = connect-awaitable-promise; explicit operation-state-task(coroutine_handle<> h) noexcept : coro(h) {}operation-state-task(operation-state-task&&) = delete; ~operation-state-task() { coro.destroy(); }void start() & noexcept {coro.resume(); }private: coroutine_handle<> coro; // exposition only};}

5

#

Let V name the typeawait-result-type<DS, connect-awaitable-promise>, let Sigs name the typecompletion_signatures<SET-VALUE-SIG(V), // see [exec.snd.concepts] set_error_t(exception_ptr), set_stopped_t()> and let connect-awaitable be an exposition-only coroutine defined as follows:namespace std::execution {template<class Fun, class... Ts>auto suspend-complete(Fun fun, Ts&&... as) noexcept { // exposition onlyauto fn = &, fun noexcept { fun(std::forward(as)...); }; struct awaiter {decltype(fn) fn; // exposition onlystatic constexpr bool await_ready() noexcept { return false; }void await_suspend(coroutine_handle<>) noexcept { fn(); }noreturn void await_resume() noexcept { unreachable(); }}; return awaiter{fn}; }operation-state-task connect-awaitable(DS sndr, DR rcvr) requires receiver_of<DR, Sigs> { exception_ptr ep; try {if constexpr (same_as<V, void>) {co_await std::move(sndr); co_await suspend-complete(set_value, std::move(rcvr)); } else {co_await suspend-complete(set_value, std::move(rcvr), co_await std::move(sndr)); }} catch(...) { ep = current_exception(); }co_await suspend-complete(set_error, std::move(rcvr), std::move(ep)); }}

6

#

The expression connect(sndr, rcvr) is expression-equivalent to:

  • (6.1)

    new_sndr.connect(rcvr) if that expression is well-formed. Mandates: The type of the expression above satisfies operation_state.

  • (6.2)

    Otherwise, connect-awaitable(new_sndr, rcvr).

Except that rcvr is evaluated only once.

Mandates: The following are true:

sender_in<Sndr, env_of_t>

receiver_of<Rcvr, completion_signatures_of_t<Sndr, env_of_t>>