diff --git a/include/exec/any_sender_of.hpp b/include/exec/any_sender_of.hpp index 3f4c847aa..3d747ce07 100644 --- a/include/exec/any_sender_of.hpp +++ b/include/exec/any_sender_of.hpp @@ -440,9 +440,7 @@ namespace exec { (*__other.__vtable_)(__copy_construct, this, __other); } - auto operator=(const __t& __other) -> __t& - requires(_Copyable) - { + auto operator=(const __t& __other) -> __t& requires(_Copyable) { if (&__other != this) { __t tmp(__other); *this = std::move(tmp); @@ -520,7 +518,8 @@ namespace exec { } template - STDEXEC_MEMFN_DECL(void __move_construct)(this __mtype<_Tp>, __t& __self, __t&& __other) noexcept { + STDEXEC_MEMFN_DECL( + void __move_construct)(this __mtype<_Tp>, __t& __self, __t&& __other) noexcept { if (!__other.__object_pointer_) { return; } @@ -540,8 +539,7 @@ namespace exec { template requires _Copyable - STDEXEC_MEMFN_DECL( - void __copy_construct)(this __mtype<_Tp>, __t& __self, const __t& __other) { + STDEXEC_MEMFN_DECL(void __copy_construct)(this __mtype<_Tp>, __t& __self, const __t& __other) { if (!__other.__object_pointer_) { return; } @@ -563,7 +561,8 @@ namespace exec { struct __empty_vtable { template - STDEXEC_MEMFN_DECL(auto __create_vtable)(this __mtype<__empty_vtable>, __mtype<_Sender>) noexcept + STDEXEC_MEMFN_DECL( + auto __create_vtable)(this __mtype<__empty_vtable>, __mtype<_Sender>) noexcept -> const __empty_vtable* { static const __empty_vtable __vtable_{}; return &__vtable_; @@ -616,11 +615,12 @@ namespace exec { , public __query_vfun<_Queries>... { public: using __query_vfun<_Queries>::operator()...; + using __any_::__rcvr_vfun<_Sigs>::operator()...; private: template requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> - && (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...) + && (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...) STDEXEC_MEMFN_DECL( auto __create_vtable)(this __mtype<__t>, __mtype<_Rcvr>) noexcept -> const __t* { static const __t __vtable_{ @@ -675,24 +675,21 @@ namespace exec { } template - requires __one_of + requires __callable<__vtable_t, void*, set_value_t, _As...> void set_value(_As&&... __as) noexcept { - const __any_::__rcvr_vfun* __vfun = __env_.__vtable_; - (*__vfun->__complete_)(__env_.__rcvr_, static_cast<_As&&>(__as)...); + (*__env_.__vtable_)(__env_.__rcvr_, set_value_t(), static_cast<_As&&>(__as)...); } template - requires __one_of + requires __callable<__vtable_t, void*, set_error_t, _Error> void set_error(_Error&& __err) noexcept { - const __any_::__rcvr_vfun* __vfun = __env_.__vtable_; - (*__vfun->__complete_)(__env_.__rcvr_, static_cast<_Error&&>(__err)); + (*__env_.__vtable_)(__env_.__rcvr_, set_error_t(), static_cast<_Error&&>(__err)); } void set_stopped() noexcept - requires __one_of + requires __callable<__vtable_t, void*, set_stopped_t> { - const __any_::__rcvr_vfun* __vfun = __env_.__vtable_; - (*__vfun->__complete_)(__env_.__rcvr_); + (*__env_.__vtable_)(__env_.__rcvr_, set_stopped_t()); } auto get_env() const noexcept -> const __env_t& { @@ -700,8 +697,8 @@ namespace exec { } }; - auto __test_never_stop_token( - get_stop_token_t (*)(never_stop_token (*)() noexcept)) -> __mbool; + auto __test_never_stop_token(get_stop_token_t (*)(never_stop_token (*)() noexcept)) + -> __mbool; template auto __test_never_stop_token(_Tag (*)(_Ret (*)(_As...) noexcept)) -> __mbool; @@ -783,7 +780,8 @@ namespace exec { private: template - STDEXEC_MEMFN_DECL(auto __create_vtable)(this __mtype<__operation_vtable>, __mtype<_Op>) noexcept + STDEXEC_MEMFN_DECL( + auto __create_vtable)(this __mtype<__operation_vtable>, __mtype<_Op>) noexcept -> const __operation_vtable* { static __operation_vtable __vtable{[](void* __object_pointer) noexcept -> void { STDEXEC_ASSERT(__object_pointer); @@ -831,8 +829,7 @@ namespace exec { template _Self, class _Item> requires __callable - STDEXEC_MEMFN_DECL( - auto set_next)(this _Self& __self, _Item&& __item) noexcept + STDEXEC_MEMFN_DECL(auto set_next)(this _Self& __self, _Item&& __item) noexcept -> __call_result_t { return exec::set_next(__self.__op_->__rcvr_, static_cast<_Item&&>(__item)); } @@ -961,7 +958,9 @@ namespace exec { __immovable_operation_storage (*__connect_)(void*, __receiver_ref_t); private: template _Sender> - STDEXEC_MEMFN_DECL(auto __create_vtable)(this __mtype<__vtable>, __mtype<_Sender>) noexcept -> const __vtable* { + STDEXEC_MEMFN_DECL( + auto + __create_vtable)(this __mtype<__vtable>, __mtype<_Sender>) noexcept -> const __vtable* { static const __vtable __vtable_{ {*__create_vtable(__mtype<__query_vtable<_SenderQueries>>{}, __mtype<_Sender>{})}, [](void* __object_pointer, __receiver_ref_t __receiver) @@ -1083,7 +1082,9 @@ namespace exec { } private: template - STDEXEC_MEMFN_DECL(auto __create_vtable)(this __mtype<__vtable>, __mtype<_Scheduler>) noexcept -> const __vtable* { + STDEXEC_MEMFN_DECL( + auto + __create_vtable)(this __mtype<__vtable>, __mtype<_Scheduler>) noexcept -> const __vtable* { static const __vtable __vtable_{ {*__create_vtable( __mtype<__query_vtable<_SchedulerQueries, false>>{}, __mtype<_Scheduler>{})}, diff --git a/include/stdexec/__detail/__receiver_ref.hpp b/include/stdexec/__detail/__receiver_ref.hpp index c0638c009..35101d058 100644 --- a/include/stdexec/__detail/__receiver_ref.hpp +++ b/include/stdexec/__detail/__receiver_ref.hpp @@ -30,16 +30,16 @@ namespace stdexec { namespace __any_ { template struct __rcvr_vfun<_Tag(_Args...)> { - void (*__complete_)(void*, _Args&&...) noexcept; + void (*__complete_)(void*, _Args...) noexcept; - void operator()(void* __obj, _Tag, _Args&&... __args) const noexcept { + void operator()(void* __obj, _Tag, _Args... __args) const noexcept { __complete_(__obj, static_cast<_Args&&>(__args)...); } }; template constexpr auto __rcvr_vfun_fn(_Obj*, _Tag (*)(_Args...)) noexcept { - return +[](void* __ptr, _Args&&... __args) noexcept { + return +[](void* __ptr, _Args... __args) noexcept { _Obj* __obj = static_cast<_Obj*>(__ptr); _Tag()(std::move(_GetReceiver()(*__obj)), static_cast<_Args&&>(__args)...); }; @@ -95,16 +95,20 @@ namespace stdexec { namespace __any_ { } template + requires __callable<__receiver_vtable_for<_Sigs, _Env>, void*, set_value_t, _As...> void set_value(_As&&... __as) noexcept { (*__vtable_)(__op_state_, set_value_t(), static_cast<_As&&>(__as)...); } template + requires __callable<__receiver_vtable_for<_Sigs, _Env>, void*, set_error_t, _Error> void set_error(_Error&& __err) noexcept { (*__vtable_)(__op_state_, set_error_t(), static_cast<_Error&&>(__err)); } - void set_stopped() noexcept { + void set_stopped() noexcept + requires __callable<__receiver_vtable_for<_Sigs, _Env>, void*, set_stopped_t> + { (*__vtable_)(__op_state_, set_stopped_t()); } diff --git a/test/exec/test_any_sender.cpp b/test/exec/test_any_sender.cpp index 190e072f9..b2ae8a952 100644 --- a/test/exec/test_any_sender.cpp +++ b/test/exec/test_any_sender.cpp @@ -36,8 +36,8 @@ namespace { template // BUGBUG ambiguous! requires stdexec::tag_invocable - auto operator()(T&& t) const - noexcept(stdexec::nothrow_tag_invocable) -> stdexec::tag_invoke_result_t { + auto operator()(T&& t) const noexcept(stdexec::nothrow_tag_invocable) + -> stdexec::tag_invoke_result_t { return stdexec::tag_invoke(*this, static_cast(t)); } }; @@ -328,6 +328,23 @@ namespace { } } + template + using my_stoppable_sender_of = + any_sender_of; + + TEST_CASE("any_sender uses overload rules for completion signatures", "[types][any_sender]") { + auto split_sender = split(just(21)); + static_assert(sender_of); + static_assert(sender_of); + my_stoppable_sender_of sender = split_sender; + + auto [value] = *sync_wait(std::move(sender)); + CHECK(value == 42); + + sender = just(21) | then([&](int) -> int { throw 420; }); + CHECK_THROWS_AS(sync_wait(std::move(sender)), int); + } + class stopped_token { private: bool stopped_{true}; @@ -686,8 +703,8 @@ namespace { return {{}, static_cast(r)}; } - auto - query(ex::get_completion_scheduler_t) const noexcept -> counting_scheduler { + auto query(ex::get_completion_scheduler_t) const noexcept + -> counting_scheduler { return {}; }