// Copyright (c) OpenMMLab. All rights reserved. #ifndef MMDEPLOY_CSRC_EXPERIMENTAL_EXECUTION_LET_VALUE_H_ #define MMDEPLOY_CSRC_EXPERIMENTAL_EXECUTION_LET_VALUE_H_ #include #include "utility.h" namespace mmdeploy { namespace __let_value { template using __decay_ref = std::decay_t&; template using __result_sender_t = __call_result_t...>; template struct __value_type {}; template struct __value_type> { using type = __result_sender_t; }; template using __value_type_t = typename __value_type::type; template struct _Storage { using Sender = remove_cvref_t; using operation_t = connect_result_t<__value_type_t>, Receiver>; std::optional> args_; // workaround for MSVC v142 toolset, copy elision does not work here std::optional<__conv_proxy> proxy_; }; template struct _Operation { struct type; }; template using operation_t = typename _Operation, Func>::type; template struct _Receiver { struct type; }; template using receiver_t = typename _Receiver::type; template struct _Receiver::type { operation_t* op_state_; template friend void tag_invoke(set_value_t, type&& self, As&&... as) noexcept { auto* op_state = self.op_state_; auto& args = op_state->storage_.args_.emplace((As &&) as...); op_state->storage_.proxy_.emplace([&] { return Connect(std::apply(std::move(op_state->func_), args), std::move(op_state->receiver_)); }); Start(**op_state->storage_.proxy_); } }; template struct _Operation::type { using _receiver_t = receiver_t; friend void tag_invoke(start_t, type& self) noexcept { Start(self.op_state2_); } template type(CvrefSender&& sender, Receiver2&& receiver, Func func) : op_state2_(Connect((CvrefSender &&) sender, _receiver_t{this})), receiver_((Receiver2 &&) receiver), func_(std::move(func)) {} connect_result_t op_state2_; Receiver receiver_; Func func_; _Storage storage_; }; template struct _Sender { struct type; }; template using sender_t = typename _Sender, Func>::type; template struct _Sender::type { template using _operation_t = operation_t<_copy_cvref_t, Receiver, Func>; using value_types = completion_signatures_of_t<__value_type_t>>; template = 0> friend auto tag_invoke(connect_t, Self&& self, Receiver&& receiver) -> _operation_t { return _operation_t{((Self &&) self).sender_, (Receiver &&) receiver, ((Self &&) self).func_}; } Sender sender_; Func func_; }; using std::enable_if_t; struct let_value_t { template && _tag_invocable_with_completion_scheduler, int> = 0> auto operator()(Sender&& sender, Func func) const { auto scheduler = GetCompletionScheduler(sender); return tag_invoke(let_value_t{}, std::move(scheduler), (Sender &&) sender, std::move(func)); } template && _tag_invocable_with_completion_scheduler && tag_invocable, int> = 0> auto operator()(Sender&& sender, Func func) const { return tag_invoke(let_value_t{}, (Sender &&) sender, std::move(func)); } template && !_tag_invocable_with_completion_scheduler && !tag_invocable, int> = 0> sender_t operator()(Sender&& sender, Func func) const { return {(Sender &&) sender, std::move(func)}; } template _BinderBack operator()(Func func) const { return {{}, {}, {std::move(func)}}; } }; } // namespace __let_value using __let_value::let_value_t; inline constexpr let_value_t LetValue{}; } // namespace mmdeploy #endif // MMDEPLOY_CSRC_EXPERIMENTAL_EXECUTION_LET_VALUE_H_