Let let-state denote the following exposition-only class template:
template<class Cpo, class Sndr, class Fn, class Rcvr, class ArgsVariant, class OpsVariant>
struct let-state {
using env_t = decltype(let-env(declval<Sndr>()), get_env(declval<Rcvr&>()));
Fn fn;
env_t env;
ArgsVariant args;
OpsVariant ops;
template<class Tag, class... Ts>
constexpr void impl(Rcvr& rcvr, Tag tag, Ts&&... ts) noexcept
{
using args_t = decayed-tuple<Ts...>;
using receiver_type = receiver2<Rcvr, env_t>;
using sender_type = apply_result_t<Fn, args_t&>;
if constexpr (is_same_v<Tag, Cpo>) {
try {
auto& tuple = args.template emplace<args_t>(std::forward<Ts>(ts)...);
ops.template emplace<monostate>();
auto&& sndr = apply(std::move(fn), tuple);
using op_t = connect_result_t<sender_type, receiver_type>;
auto mkop2 = [&] {
return connect(std::forward<sender_type>(sndr),
receiver_type{rcvr, env});
};
auto& op = ops.template emplace<op_t>(emplace-from{mkop2});
start(op);
} catch (...) {
constexpr bool nothrow =
is_nothrow_constructible_v<args_t, Ts...> &&
is_nothrow_applicable_v<Fn, args_t&> &&
noexcept(connect(declval<sender_type>(), receiver_type{rcvr, env}));
if constexpr (!nothrow) {
set_error(std::move(rcvr), current_exception());
}
}
} else {
tag(std::move(rcvr), std::forward<Ts>(ts)...);
}
}
struct receiver {
let-state& state;
Rcvr& rcvr;
using receiver_concept = receiver_tag;
template<class... Args>
constexpr void set_value(Args&&... args) noexcept {
state.impl(rcvr, execution::set_value, std::forward<Args>(args)...);
}
template<class... Args>
constexpr void set_error(Args&&... args) noexcept {
state.impl(rcvr, execution::set_error, std::forward<Args>(args)...);
}
template<class... Args>
constexpr void set_stopped(Args&&... args) noexcept {
state.impl(rcvr, execution::set_stopped, std::forward<Args>(args)...);
}
constexpr env_of_t<const Rcvr&> get_env() const noexcept {
return execution::get_env(rcvr);
}
};
using op_t = connect_result_t<Sndr, receiver>;
constexpr let-state(Sndr&& sndr, Fn fn, Rcvr& rcvr)
: fn(std::move(fn)), env(let-env(sndr), get_env(rcvr)),
ops(in_place_type<op_t>, std::forward<Sndr>(sndr), receiver{*this, rcvr}) {}
};