#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace unifex { namespace _upon_error { namespace detail { template struct result_overload { using type = type_list; }; template<> struct result_overload { using type = type_list<>; }; template using result_overload_t = typename result_overload::type; } // namespace detail template struct _receiver { struct type; }; template using receiver_t = typename _receiver::type; template struct _receiver::type { UNIFEX_NO_UNIQUE_ADDRESS Func func_; UNIFEX_NO_UNIQUE_ADDRESS Receiver receiver_; template (typename... Values) (requires receiver_of) void set_value(Values&&... values) && { unifex::set_value((Receiver &&)(receiver_), (Values &&)(values)...); } template (typename Error) (requires receiver) void set_error(Error&& error) && noexcept{ using result_t = std::invoke_result_t; if constexpr (std::is_void_v) { if constexpr (noexcept(std::invoke((Func &&) func_, (Error &&) error))) { std::invoke((Func &&) func_, (Error &&) error); unifex::set_value((Receiver &&) receiver_); } else { UNIFEX_TRY { std::invoke((Func &&) func_, (Error &&) error); unifex::set_value((Receiver &&) receiver_); } UNIFEX_CATCH(...) { unifex::set_error((Receiver &&) receiver_, std::current_exception()); } } } else { if constexpr (noexcept(std::invoke((Func &&) func_, (Error &&) error))) { unifex::set_value( (Receiver &&) receiver_, std::invoke((Func &&) func_, (Error &&) error)); } else { UNIFEX_TRY { unifex::set_value( (Receiver &&) receiver_, std::invoke((Func &&) func_, (Error &&) error)); } UNIFEX_CATCH(...) { unifex::set_error((Receiver &&) receiver_, std::current_exception()); } } } } void set_done() && noexcept { unifex::set_done((Receiver &&)(receiver_)); } template(typename CPO) (requires is_receiver_query_cpo_v) friend auto tag_invoke( CPO cpo, const type& r) noexcept( is_nothrow_callable_v) -> callable_result_t { return (CPO &&)(cpo)(std::as_const(r.receiver_)); } template friend void tag_invoke(tag_t, const type& self, Visit&& visit) { std::invoke(visit, self.receiver_); } }; template struct _sender { struct type; }; template using sender = typename _sender, std::decay_t>::type; template struct _sender::type { UNIFEX_NO_UNIQUE_ADDRESS Predecessor pred_; UNIFEX_NO_UNIQUE_ADDRESS Func func_; private: /* * This helper returns type_list> if invoking func returns * Result else if func returns void then helper returns type_list> */ template using invoked_result_t = type_list>>; public: template < template class Variant, template class Tuple> using value_types = type_list_nested_apply_t< concat_type_lists_unique_t< sender_value_types_t, sender_error_types_t>, Variant, Tuple>; template