From 9d2403f3164f40ab497d219053dc37f51e004650 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Thu, 11 Apr 2024 17:06:34 -0700 Subject: [PATCH 1/3] Use std::is_invocable variants These are drop in replacements of is_callable variants and we can replace our concept shim with them as well. --- include/unifex/allocate.hpp | 2 +- include/unifex/any_scheduler.hpp | 4 +- include/unifex/any_sender_of.hpp | 12 ++-- include/unifex/at_coroutine_exit.hpp | 8 +-- include/unifex/await_transform.hpp | 6 +- include/unifex/bind_back.hpp | 24 +++---- include/unifex/bulk_join.hpp | 6 +- include/unifex/bulk_schedule.hpp | 2 +- include/unifex/bulk_transform.hpp | 16 ++--- include/unifex/config.hpp.in | 4 +- include/unifex/connect_awaitable.hpp | 8 +-- include/unifex/continuations.hpp | 4 +- include/unifex/create.hpp | 8 +-- include/unifex/defer.hpp | 8 +-- include/unifex/delay.hpp | 2 +- include/unifex/dematerialize.hpp | 12 ++-- include/unifex/detail/concept_macros.hpp | 15 ----- include/unifex/detail/debug_async_scope.hpp | 4 +- include/unifex/detail/vtable.hpp | 4 +- include/unifex/filter_stream.hpp | 6 +- include/unifex/finally.hpp | 26 ++++---- include/unifex/find_if.hpp | 12 ++-- include/unifex/for_each.hpp | 4 +- include/unifex/get_stop_token.hpp | 4 +- include/unifex/indexed_for.hpp | 6 +- include/unifex/into_variant.hpp | 8 +-- include/unifex/just_from.hpp | 6 +- include/unifex/let_done.hpp | 38 +++++------ include/unifex/let_error.hpp | 26 ++++---- include/unifex/let_value.hpp | 10 +-- include/unifex/let_value_with.hpp | 22 +++---- include/unifex/let_value_with_stop_source.hpp | 6 +- include/unifex/let_value_with_stop_token.hpp | 6 +- include/unifex/manual_lifetime.hpp | 18 ++--- include/unifex/manual_lifetime_union.hpp | 4 +- include/unifex/materialize.hpp | 8 +-- include/unifex/nest.hpp | 4 +- include/unifex/on_stream.hpp | 2 +- include/unifex/receiver_concepts.hpp | 6 +- include/unifex/reduce_stream.hpp | 14 ++-- include/unifex/repeat_effect_until.hpp | 8 +-- include/unifex/retry_when.hpp | 14 ++-- include/unifex/schedule_with_subscheduler.hpp | 4 +- include/unifex/sender_concepts.hpp | 4 +- include/unifex/sender_for.hpp | 8 +-- include/unifex/sequence.hpp | 26 ++++---- include/unifex/single.hpp | 2 +- include/unifex/spawn_detached.hpp | 4 +- include/unifex/spawn_future.hpp | 8 +-- include/unifex/std_concepts.hpp | 5 -- include/unifex/stop_immediately.hpp | 2 +- include/unifex/stop_when.hpp | 10 +-- include/unifex/sync_wait.hpp | 2 +- include/unifex/take_until.hpp | 14 ++-- include/unifex/then.hpp | 6 +- include/unifex/transform_stream.hpp | 2 +- include/unifex/type_erased_stream.hpp | 2 +- include/unifex/type_traits.hpp | 65 ------------------- include/unifex/upon_done.hpp | 12 ++-- include/unifex/upon_error.hpp | 6 +- include/unifex/v0/async_scope.hpp | 6 +- include/unifex/v1/async_scope.hpp | 12 ++-- include/unifex/v1/debug_async_scope.hpp | 12 ++-- include/unifex/via.hpp | 2 +- include/unifex/via_stream.hpp | 2 +- include/unifex/when_all.hpp | 6 +- include/unifex/when_all_range.hpp | 6 +- .../unifex/win32/low_latency_iocp_context.hpp | 6 +- include/unifex/win32/windows_thread_pool.hpp | 8 +-- include/unifex/with_allocator.hpp | 2 +- include/unifex/with_query_value.hpp | 8 +-- test/any_object_test.cpp | 2 +- test/let_value_with_stop_token_test.cpp | 10 +-- 73 files changed, 293 insertions(+), 378 deletions(-) diff --git a/include/unifex/allocate.hpp b/include/unifex/allocate.hpp index 77901c3d2..40469d432 100644 --- a/include/unifex/allocate.hpp +++ b/include/unifex/allocate.hpp @@ -147,7 +147,7 @@ inline const struct _fn { return _alloc::sender{(Sender &&) predecessor}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/any_scheduler.hpp b/include/unifex/any_scheduler.hpp index 7f5b68629..762f74979 100644 --- a/include/unifex/any_scheduler.hpp +++ b/include/unifex/any_scheduler.hpp @@ -187,7 +187,7 @@ struct _with::any_scheduler { template(typename Receiver) // (requires receiver_of AND( - invocable&&...)) // + std::is_invocable_v&&...)) // any_operation_state_for connect(Receiver rec) && { any_scheduler_impl const& impl = sched_.impl_; return any_operation_state_for{ @@ -281,7 +281,7 @@ struct _with::any_scheduler_ref { template(typename Receiver) // (requires receiver_of AND( - invocable&&...)) // + std::is_invocable_v&&...)) // any_operation_state_for connect(Receiver rec) && { any_scheduler_ref_impl const& impl = sched_.impl_; return any_operation_state_for{ diff --git a/include/unifex/any_sender_of.hpp b/include/unifex/any_sender_of.hpp index 2feb43d54..b182d9355 100644 --- a/include/unifex/any_sender_of.hpp +++ b/include/unifex/any_sender_of.hpp @@ -174,9 +174,9 @@ struct _op_for::type { // to the receiver after unsubscribing the stop token. template(typename CPO, typename... Args) // (requires is_receiver_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend void tag_invoke(CPO cpo, type&& self, Args&&... args) noexcept( - is_nothrow_callable_v) { + std::is_nothrow_invocable_v) { self.subscription_.unsubscribe(); cpo(std::move(self).rec_, (Args &&) args...); } @@ -184,10 +184,10 @@ struct _op_for::type { // Forward other receiver queries template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const type& self) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(self.rec_); } @@ -238,7 +238,7 @@ struct _with::_sender::type template(typename Receiver) // (requires receiver_of AND( - invocable&&...)) // + std::is_invocable_v&&...)) // _operation_state_for connect(Receiver r) && { any_unique_t<_connect, Values...>>& self = *this; return _operation_state_for{ diff --git a/include/unifex/at_coroutine_exit.hpp b/include/unifex/at_coroutine_exit.hpp index 8319d0d5e..8055679ae 100644 --- a/include/unifex/at_coroutine_exit.hpp +++ b/include/unifex/at_coroutine_exit.hpp @@ -165,10 +165,10 @@ struct _die_on_done_rec { template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const type& p) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return cpo(p.rec_); } }; @@ -313,7 +313,7 @@ inline constexpr struct _fn { public: template(typename Action, typename... Ts) // - (requires callable, std::decay_t...>) // + (requires std::is_invocable_v, std::decay_t...>) // _cleanup_task...> operator()(Action&& action, Ts&&... ts) const { return _fn::at_coroutine_exit((Action &&) action, (Ts &&) ts...); diff --git a/include/unifex/await_transform.hpp b/include/unifex/await_transform.hpp index 4641499ae..028bf72c8 100644 --- a/include/unifex/await_transform.hpp +++ b/include/unifex/await_transform.hpp @@ -122,10 +122,10 @@ struct _awaitable_base::type { template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const _rec& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { const Promise& p = r.continuation_.promise(); return std::move(cpo)(p); } diff --git a/include/unifex/bind_back.hpp b/include/unifex/bind_back.hpp index 7b1c6c14b..2cf87e61b 100644 --- a/include/unifex/bind_back.hpp +++ b/include/unifex/bind_back.hpp @@ -31,9 +31,9 @@ namespace _compose { struct _fn { template auto operator()(Target&& target, Other&& other, Self&& self) const noexcept( - is_nothrow_callable_v&& - is_nothrow_callable_v>) - -> callable_result_t> { + std::is_nothrow_invocable_v&& + std::is_nothrow_invocable_v>) + -> std::invoke_result_t> { return ((Self &&) self)(((Other &&) other)((Target &&) target)); } }; @@ -56,11 +56,11 @@ struct _apply_fn_impl::type { Target&& target_; template(typename... ArgN) // - (requires callable) // + (requires std::is_invocable_v) // auto operator()(ArgN&&... argN) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return ((Cpo &&) cpo_)((Target &&) target_, (ArgN &&) argN...); } }; @@ -82,19 +82,19 @@ struct _result_impl::type : _result_base { template(typename Target) // (requires(!derived_from, _result_base>) - AND callable) // + AND std::is_invocable_v) // decltype(auto) operator()(Target&& target) const& noexcept( - is_nothrow_callable_v) { + std::is_nothrow_invocable_v) { return std::apply( _apply_fn{cpo_, (Target &&) target}, argN_); } template(typename Target) // (requires(!derived_from, _result_base>) - AND callable) // + AND std::is_invocable_v) // decltype(auto) operator()(Target&& target) && noexcept( - is_nothrow_callable_v) { + std::is_nothrow_invocable_v) { return std::apply( _apply_fn{(Cpo &&) cpo_, (Target &&) target}, std::move(argN_)); @@ -104,10 +104,10 @@ struct _result_impl::type : _result_base { (requires(!derived_from< remove_cvref_t, _result_base>) AND same_as, type> AND - callable, Target, member_t...>) // + std::is_invocable_v, Target, member_t...>) // friend decltype(auto) operator|(Target&& target, Self&& self) noexcept( - is_nothrow_callable_v< + std::is_nothrow_invocable_v< member_t, Target, member_t...>) { diff --git a/include/unifex/bulk_join.hpp b/include/unifex/bulk_join.hpp index 0ed158a37..6873a3cce 100644 --- a/include/unifex/bulk_join.hpp +++ b/include/unifex/bulk_join.hpp @@ -74,8 +74,8 @@ class _join_receiver::type { Self, type>) // friend auto tag_invoke(CPO cpo, const Self& self) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return cpo(self.receiver_); } @@ -166,7 +166,7 @@ struct _fn { return join_sender>{(Source &&) source}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/bulk_schedule.hpp b/include/unifex/bulk_schedule.hpp index 4c9326bed..e13f1e910 100644 --- a/include/unifex/bulk_schedule.hpp +++ b/include/unifex/bulk_schedule.hpp @@ -239,7 +239,7 @@ struct _fn { } template constexpr auto operator()(Integral n) const - noexcept(is_nothrow_callable_v, _fn, Integral>) + noexcept(std::is_nothrow_invocable_v, _fn, Integral>) -> bind_back_result_t<_fn, Integral> { return bind_back(*this, n); } diff --git a/include/unifex/bulk_transform.hpp b/include/unifex/bulk_transform.hpp index 9394f5dc0..3988a786d 100644 --- a/include/unifex/bulk_transform.hpp +++ b/include/unifex/bulk_transform.hpp @@ -47,7 +47,7 @@ class _tfx_receiver::type { , policy_(std::move(policy)) {} template(typename... Values) // - (requires invocable AND + (requires std::is_invocable_v AND std::is_void_v>) // @@ -59,7 +59,7 @@ class _tfx_receiver::type { } template(typename... Values) // - (requires invocable AND( + (requires std::is_invocable_v AND( !std::is_void_v>)) // @@ -115,8 +115,8 @@ class _tfx_receiver::type { Self, type>) // friend auto tag_invoke(CPO cpo, const Self& self) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return cpo(self.receiver_); } @@ -238,8 +238,8 @@ struct _fn { (requires bulk_sender) // auto operator()(Source&& s, Func&& f) const - noexcept(is_nothrow_callable_v<_fn, Source, Func, FuncPolicy>) - -> callable_result_t<_fn, Source, Func, FuncPolicy> { + noexcept(std::is_nothrow_invocable_v<_fn, Source, Func, FuncPolicy>) + -> std::invoke_result_t<_fn, Source, Func, FuncPolicy> { return operator()((Source &&) s, (Func &&) f, get_execution_policy(f)); } @@ -271,13 +271,13 @@ struct _fn { } template constexpr auto operator()(Func&& f) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&) f); } template constexpr auto operator()(Func&& f, FuncPolicy policy) const - noexcept(is_nothrow_callable_v, _fn, Func, FuncPolicy>) + noexcept(std::is_nothrow_invocable_v, _fn, Func, FuncPolicy>) -> bind_back_result_t<_fn, Func, FuncPolicy> { return bind_back(*this, (Func &&) f, (FuncPolicy &&) policy); } diff --git a/include/unifex/config.hpp.in b/include/unifex/config.hpp.in index adbe665cc..74314ef9b 100644 --- a/include/unifex/config.hpp.in +++ b/include/unifex/config.hpp.in @@ -126,7 +126,7 @@ // class foo_sender { // template< // typename Receiver, -// std::enable_if_t, Receiver, foo>, int> = 0> +// std::enable_if_t, Receiver, foo>, int> = 0> // friend auto tag_invoke(tag_t, foo_sender&& s, Receiver&& r) -> foo_operation { // return ...; // } @@ -139,7 +139,7 @@ // typename Receiver, // UNIFEX_DECLARE_NON_DEDUCED_TYPE(CPO, tag_t), // UNIFEX_DECLARE_NON_DEDUCED_TYPE(S, foo_sender), -// std::enable_if_t, Receiver, foo>, int> = 0? +// std::enable_if_t, Receiver, foo>, int> = 0? // friend auto tag_invoke( // UNIFEX_USE_NON_DEDUCED_TYPE(CPO, tag_t), // UNIFEX_USE_NON_DEDUCED_TYPE(S, foo_sender)&& s, diff --git a/include/unifex/connect_awaitable.hpp b/include/unifex/connect_awaitable.hpp index b9c2fbda3..b5b1ef439 100644 --- a/include/unifex/connect_awaitable.hpp +++ b/include/unifex/connect_awaitable.hpp @@ -95,10 +95,10 @@ class _sender_task::type { template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const promise_type& p) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return cpo(std::as_const(p.receiver_)); } @@ -148,7 +148,7 @@ inline const struct _fn { // awaitable through unifex::await_transform. So take that into // consideration when computing the result type: using promise_type = typename _await::sender_task::promise_type; - using awaitable_type = callable_result_t< + using awaitable_type = std::invoke_result_t< tag_t, promise_type&, Awaitable>; diff --git a/include/unifex/continuations.hpp b/include/unifex/continuations.hpp index 44a4135a4..7d1157297 100644 --- a/include/unifex/continuations.hpp +++ b/include/unifex/continuations.hpp @@ -31,11 +31,11 @@ namespace _visit_continuations_cpo { inline const struct _fn { #if !UNIFEX_NO_COROUTINES template(typename Promise, typename Func) // - (requires(!same_as) AND callable<_fn, Promise&, Func>) // + (requires(!same_as) AND std::is_invocable_v<_fn, Promise&, Func>) // friend void tag_invoke( _fn cpo, coro::coroutine_handle h, - Func&& func) noexcept(is_nothrow_callable_v<_fn, Promise&, Func>) { + Func&& func) noexcept(std::is_nothrow_invocable_v<_fn, Promise&, Func>) { cpo(h.promise(), (Func &&) func); } #endif // UNIFEX_NO_COROUTINES diff --git a/include/unifex/create.hpp b/include/unifex/create.hpp index 88670c791..f999d3c5a 100644 --- a/include/unifex/create.hpp +++ b/include/unifex/create.hpp @@ -87,10 +87,10 @@ struct _op { // Forward other receiver queries template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const type& self) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(self.rec_); } @@ -219,7 +219,7 @@ struct _fn { * \endcode * \tparam ValueTypes The value types of the resulting sender. Should be the * list of value type(s) accepted by the callback (with the exception of the - * void* context). \param[in] fn A void-returning callable that accepts an + * void* context). \param[in] fn A void-returning invocable that accepts an * lvalue reference to an object whose type satisfies the \c * unifex::receiver_of concept. This function should dispatch to * the C-style callback (see example). \param[in] ctx An optional extra bit of diff --git a/include/unifex/defer.hpp b/include/unifex/defer.hpp index a1e0d2689..74395f2ba 100644 --- a/include/unifex/defer.hpp +++ b/include/unifex/defer.hpp @@ -25,10 +25,10 @@ namespace unifex { namespace _defer { inline const struct _fn { template(typename Callable)( - requires callable AND - sender>) constexpr auto - operator()(Callable&& callable) const { - return let_value(just(), (Callable &&) callable); + requires std::is_invocable_v AND + sender>) constexpr auto + operator()(Callable&& invocable) const { + return let_value(just(), (Callable &&) invocable); } } defer{}; } // namespace _defer diff --git a/include/unifex/delay.hpp b/include/unifex/delay.hpp index 45bf90f44..f2c5d2e32 100644 --- a/include/unifex/delay.hpp +++ b/include/unifex/delay.hpp @@ -43,7 +43,7 @@ inline const struct _fn { template constexpr auto operator()(Scheduler&& scheduler, Duration&& duration) const noexcept( - is_nothrow_callable_v, _fn, Scheduler, Duration>) + std::is_nothrow_invocable_v, _fn, Scheduler, Duration>) -> bind_back_result_t<_fn, Scheduler, Duration> { return bind_back(*this, (Scheduler &&) scheduler, (Duration &&) duration); } diff --git a/include/unifex/dematerialize.hpp b/include/unifex/dematerialize.hpp index c2df70775..24d3eb751 100644 --- a/include/unifex/dematerialize.hpp +++ b/include/unifex/dematerialize.hpp @@ -51,12 +51,12 @@ class _receiver::type { : receiver_(static_cast(receiver)) {} template(typename CPO, typename... Values) // - (requires is_receiver_cpo_v AND is_callable_v< + (requires is_receiver_cpo_v AND std::is_invocable_v< CPO, Receiver, Values...>) // void set_value(CPO cpo, Values&&... values) && noexcept( - is_nothrow_callable_v) { + std::is_nothrow_invocable_v) { static_cast(cpo)( static_cast(receiver_), static_cast(values)...); } @@ -73,14 +73,14 @@ class _receiver::type { } template(typename CPO, UNIFEX_DECLARE_NON_DEDUCED_TYPE(R, type)) // - (requires is_receiver_query_cpo_v AND is_callable_v< + (requires is_receiver_query_cpo_v AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke( CPO cpo, const UNIFEX_USE_NON_DEDUCED_TYPE(R, type) & - r) noexcept(is_nothrow_callable_v) - -> callable_result_t { + r) noexcept(std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(std::as_const(r.receiver_)); } @@ -229,7 +229,7 @@ inline const struct _fn { return _demat::sender{(Sender &&) predecessor}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/detail/concept_macros.hpp b/include/unifex/detail/concept_macros.hpp index 83937c638..88d457f06 100644 --- a/include/unifex/detail/concept_macros.hpp +++ b/include/unifex/detail/concept_macros.hpp @@ -374,21 +374,6 @@ template inline constexpr std::enable_if_t requires_ = 0; #endif -#if UNIFEX_CXX_CONCEPTS -template -concept // - callable = // - requires(Fn&& fn, As&&... as) { - ((Fn &&) fn)((As &&) as...); -}; -#else -template -UNIFEX_CONCEPT // - callable = // - sizeof(decltype(_is_callable::_try_call(static_cast( - nullptr)))) == sizeof(_is_callable::yes_type); -#endif - } // namespace unifex #include diff --git a/include/unifex/detail/debug_async_scope.hpp b/include/unifex/detail/debug_async_scope.hpp index 0c1a5e16d..8c39e3b5f 100644 --- a/include/unifex/detail/debug_async_scope.hpp +++ b/include/unifex/detail/debug_async_scope.hpp @@ -148,8 +148,8 @@ struct _receiver::type final { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_->receiver_)); } }; diff --git a/include/unifex/detail/vtable.hpp b/include/unifex/detail/vtable.hpp index cd28bdc9f..b5314a13f 100644 --- a/include/unifex/detail/vtable.hpp +++ b/include/unifex/detail/vtable.hpp @@ -32,12 +32,12 @@ inline constexpr bool supports_type_erased_cpo_v = false; template inline constexpr bool supports_type_erased_cpo_v = - is_callable_r_v...>; + std::is_invocable_r_v...>; template inline constexpr bool supports_type_erased_cpo_v = - is_nothrow_callable_r_v...>; + std::is_nothrow_invocable_r_v...>; template inline constexpr bool supports_type_erased_cpos_v = diff --git a/include/unifex/filter_stream.hpp b/include/unifex/filter_stream.hpp index 72e44179d..8f4b75a13 100644 --- a/include/unifex/filter_stream.hpp +++ b/include/unifex/filter_stream.hpp @@ -57,8 +57,8 @@ struct _next_receiver::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -239,7 +239,7 @@ struct _fn { template constexpr auto operator()(FilterFunc&& filterFunc) const - noexcept(is_nothrow_callable_v, _fn, FilterFunc>) + noexcept(std::is_nothrow_invocable_v, _fn, FilterFunc>) -> bind_back_result_t<_fn, FilterFunc> { return bind_back(*this, std::forward(filterFunc)); } diff --git a/include/unifex/finally.hpp b/include/unifex/finally.hpp index bc51a02b2..697ab4bbb 100644 --- a/include/unifex/finally.hpp +++ b/include/unifex/finally.hpp @@ -147,12 +147,12 @@ class _value_receiver::type template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND same_as AND - is_callable_v< + std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(r.get_receiver()); } @@ -256,12 +256,12 @@ class _error_receiver::type template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND same_as AND - is_callable_v< + std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(r.get_receiver()); } @@ -320,12 +320,12 @@ class _done_receiver::type final { template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND same_as AND - is_callable_v< + std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(r.get_receiver()); } @@ -454,12 +454,12 @@ class _receiver::type final { template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND same_as AND - is_callable_v< + std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(r.get_receiver()); } @@ -716,7 +716,7 @@ struct _fn { } template constexpr auto operator()(CompletionSender&& completion) const - noexcept(is_nothrow_callable_v, _fn, CompletionSender>) + noexcept(std::is_nothrow_invocable_v, _fn, CompletionSender>) -> bind_back_result_t<_fn, CompletionSender> { return bind_back(*this, (CompletionSender &&) completion); } diff --git a/include/unifex/find_if.hpp b/include/unifex/find_if.hpp index c48cd69f1..e15785dbd 100644 --- a/include/unifex/find_if.hpp +++ b/include/unifex/find_if.hpp @@ -129,8 +129,8 @@ struct _receiver::type { R, unpack_receiver>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.output_receiver_)); } }; @@ -305,8 +305,8 @@ struct _receiver::type { template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND same_as) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.receiver_)); } @@ -329,7 +329,7 @@ struct _operation_state { template using find_if_apply_t = connect_result_t< - callable_result_t< + std::invoke_result_t< typename receiver_type::find_if_helper, std::decay_t>&&, FuncPolicy, @@ -486,7 +486,7 @@ inline const struct _fn { } template constexpr auto operator()(Func&& f, const FuncPolicy& policy) const noexcept( - is_nothrow_callable_v, _fn, Func, const FuncPolicy&>) + std::is_nothrow_invocable_v, _fn, Func, const FuncPolicy&>) -> bind_back_result_t<_fn, Func, const FuncPolicy&> { return bind_back(*this, (Func &&) f, policy); } diff --git a/include/unifex/for_each.hpp b/include/unifex/for_each.hpp index 7aa8fbad3..cc10291a0 100644 --- a/include/unifex/for_each.hpp +++ b/include/unifex/for_each.hpp @@ -29,7 +29,7 @@ template struct _map { Func func_; template(typename... Ts) // - (requires invocable) // + (requires std::is_invocable_v) // unit operator()(unit s, Ts&&... values) noexcept( std::is_nothrow_invocable_v) { @@ -80,7 +80,7 @@ inline const struct _fn { } template constexpr auto operator()(Func&& f) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&) f); } diff --git a/include/unifex/get_stop_token.hpp b/include/unifex/get_stop_token.hpp index 898282280..3391747c0 100644 --- a/include/unifex/get_stop_token.hpp +++ b/include/unifex/get_stop_token.hpp @@ -51,7 +51,7 @@ inline const struct _fn { Tag, tag_t>) // friend auto tag_invoke(Tag, Promise& promise, _awaitable) noexcept { - return _awaiter>{_fn{}(promise)}; + return _awaiter>{_fn{}(promise)}; } }; @@ -83,7 +83,7 @@ inline const struct _fn { using _get_stop_token::get_stop_token; template -using get_stop_token_result_t = callable_result_t, T>; +using get_stop_token_result_t = std::invoke_result_t, T>; template using stop_token_type_t = remove_cvref_t>; diff --git a/include/unifex/indexed_for.hpp b/include/unifex/indexed_for.hpp index 4a7021521..d0f2165c4 100644 --- a/include/unifex/indexed_for.hpp +++ b/include/unifex/indexed_for.hpp @@ -122,8 +122,8 @@ struct _receiver::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.receiver_)); } @@ -208,7 +208,7 @@ struct _fn { template constexpr auto operator()(Policy&& policy, Range&& range, Func&& f) const noexcept( - is_nothrow_callable_v, _fn, Policy, Range, Func>) + std::is_nothrow_invocable_v, _fn, Policy, Range, Func>) -> bind_back_result_t<_fn, Policy, Range, Func> { return bind_back(*this, (Policy &&) policy, (Range &&) range, (Func &&) f); } diff --git a/include/unifex/into_variant.hpp b/include/unifex/into_variant.hpp index 8c10cd958..9d47b282b 100644 --- a/include/unifex/into_variant.hpp +++ b/include/unifex/into_variant.hpp @@ -61,10 +61,10 @@ struct _receiver::type { template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const type& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.receiver_)); } @@ -170,7 +170,7 @@ struct _fn { return _into_variant::sender{(Sender &&) predecessor}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/just_from.hpp b/include/unifex/just_from.hpp index 78dfed28b..1dfa07b7d 100644 --- a/include/unifex/just_from.hpp +++ b/include/unifex/just_from.hpp @@ -25,10 +25,10 @@ namespace unifex { namespace _just_from { inline const struct _fn { template(typename Callable) // - (requires callable) // + (requires std::is_invocable_v) // constexpr auto - operator()(Callable&& callable) const { - return then(just(), (Callable &&) callable); + operator()(Callable&& invocable) const { + return then(just(), (Callable &&) invocable); } } just_from{}; } // namespace _just_from diff --git a/include/unifex/let_done.hpp b/include/unifex/let_done.hpp index 50151bfea..66c192def 100644 --- a/include/unifex/let_done.hpp +++ b/include/unifex/let_done.hpp @@ -69,7 +69,7 @@ template class _rcvr::type { using operation = operation_type; using final_receiver = final_receiver_type; - using final_sender_t = callable_result_t; + using final_sender_t = std::invoke_result_t; public: explicit type(operation* op) noexcept : op_(op) {} @@ -88,7 +88,7 @@ class _rcvr::type { UNIFEX_ASSERT(op_ != nullptr); auto op = op_; // preserve pointer value. if constexpr ( - is_nothrow_callable_v && + std::is_nothrow_invocable_v && is_nothrow_connectable_v) { op->startedOp_ = 0; unifex::deactivate_union_member(op->sourceOp_); @@ -123,12 +123,12 @@ class _rcvr::type { private: template(typename CPO, typename Self) // (requires is_receiver_query_cpo_v AND - same_as, type> AND is_callable_v< + same_as, type> AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, Self&& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -138,7 +138,7 @@ class _rcvr::type { tag_t, const type& r, VisitFunc&& - func) noexcept(is_nothrow_callable_v) { + func) noexcept(std::is_nothrow_invocable_v) { func(r.get_receiver()); } #endif @@ -183,10 +183,10 @@ class _frcvr::type { private: template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const type& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -196,7 +196,7 @@ class _frcvr::type { tag_t, const type& r, VisitFunc&& - func) noexcept(is_nothrow_callable_v) { + func) noexcept(std::is_nothrow_invocable_v) { func(r.get_receiver()); } #endif @@ -245,7 +245,7 @@ class _op::type { using source_op_t = connect_result_t; - using final_sender_t = callable_result_t; + using final_sender_t = std::invoke_result_t; using final_op_t = connect_result_t; @@ -260,7 +260,7 @@ class _op::type { template class _sndr::type { - using final_sender_t = callable_result_t; + using final_sender_t = std::invoke_result_t; public: template < @@ -342,8 +342,8 @@ namespace _cpo { struct _fn { template(typename Source, typename Done) // (requires tag_invocable<_fn, Source, Done> AND sender AND - callable> AND - sender>>) // + std::is_invocable_v> AND + sender>>) // auto operator()(Source&& source, Done&& done) const noexcept(is_nothrow_tag_invocable_v<_fn, Source, Done>) @@ -355,8 +355,8 @@ struct _fn { (requires(!tag_invocable<_fn, Source, Done>) AND sender AND constructible_from, Source> AND constructible_from, Done> AND - callable> AND - sender>>) // + std::is_invocable_v> AND + sender>>) // auto operator()(Source&& source, Done&& done) const noexcept(std::is_nothrow_constructible_v< @@ -367,11 +367,11 @@ struct _fn { (Source &&) source, (Done &&) done}; } template(typename Done) // - (requires callable> AND - sender>>) // + (requires std::is_invocable_v AND + sender>) // constexpr auto operator()(Done&& done) const - noexcept(is_nothrow_callable_v, _fn, Done>) + noexcept(std::is_nothrow_invocable_v, _fn, Done>) -> bind_back_result_t<_fn, Done> { return bind_back(*this, (Done &&) done); } diff --git a/include/unifex/let_error.hpp b/include/unifex/let_error.hpp index 16186cda1..9718e0792 100644 --- a/include/unifex/let_error.hpp +++ b/include/unifex/let_error.hpp @@ -108,7 +108,7 @@ class _rcvr::type final { auto op = op_; UNIFEX_ASSERT(op != nullptr); - using final_sender_t = callable_result_t&>; + using final_sender_t = std::invoke_result_t&>; using final_op_t = connect_result_t< final_sender_t, final_receiver>>; @@ -140,12 +140,12 @@ class _rcvr::type final { private: template(typename CPO, typename Self) // (requires is_receiver_query_cpo_v AND - same_as, type> AND is_callable_v< + same_as, type> AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, Self&& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -155,7 +155,7 @@ class _rcvr::type final { tag_t, const type& r, VisitFunc&& - func) noexcept(is_nothrow_callable_v) { + func) noexcept(std::is_nothrow_invocable_v) { func(r.get_receiver()); } #endif @@ -218,7 +218,7 @@ class _frcvr::type final { private: static void cleanup(operation* op) noexcept { - using final_sender_t = callable_result_t; + using final_sender_t = std::invoke_result_t; using final_op_t = connect_result_t; UNIFEX_ASSERT(op != nullptr); unifex::deactivate_union_member(op->finalOp_); @@ -227,10 +227,10 @@ class _frcvr::type final { template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const type& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -240,7 +240,7 @@ class _frcvr::type final { tag_t, const type& r, VisitFunc&& - func) noexcept(is_nothrow_callable_v) { + func) noexcept(std::is_nothrow_invocable_v) { func(r.get_receiver()); } #endif @@ -297,7 +297,7 @@ class _op::type final { using source_op_t = connect_result_t; template - using final_sender_t = callable_result_t&>; + using final_sender_t = std::invoke_result_t&>; template using final_receiver_t = @@ -346,7 +346,7 @@ struct max_blocking_kind { template class _sndr::type final { template - using final_sender = callable_result_t&>; + using final_sender = std::invoke_result_t&>; using final_senders_list = map_type_list_t, final_sender>; @@ -473,7 +473,7 @@ struct _fn final { } template constexpr auto operator()(Func&& func) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&) func); } diff --git a/include/unifex/let_value.hpp b/include/unifex/let_value.hpp index 5e5236390..6e0e579c0 100644 --- a/include/unifex/let_value.hpp +++ b/include/unifex/let_value.hpp @@ -100,8 +100,8 @@ struct _successor_receiver::type { template(typename CPO) // (requires is_receiver_query_cpo_v) // friend auto tag_invoke(CPO cpo, const successor_receiver& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.get_receiver())); } @@ -207,8 +207,8 @@ struct _predecessor_receiver::type { template(typename CPO) // (requires is_receiver_query_cpo_v) // friend auto tag_invoke(CPO cpo, const predecessor_receiver& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.get_receiver())); } @@ -451,7 +451,7 @@ struct _fn { } template constexpr auto operator()(SuccessorFactory&& func) const - noexcept(is_nothrow_callable_v, _fn, SuccessorFactory>) + noexcept(std::is_nothrow_invocable_v, _fn, SuccessorFactory>) -> bind_back_result_t<_fn, SuccessorFactory> { return bind_back(*this, (SuccessorFactory &&) func); } diff --git a/include/unifex/let_value_with.hpp b/include/unifex/let_value_with.hpp index 1e85620d3..a200b64ff 100644 --- a/include/unifex/let_value_with.hpp +++ b/include/unifex/let_value_with.hpp @@ -49,7 +49,7 @@ template class _sender::type { public: using InnerOp = - std::invoke_result_t&>; + std::invoke_result_t&>; template < template @@ -79,15 +79,15 @@ class _sender::type { tag_t, Self&& self, Receiver&& - r) noexcept(is_nothrow_callable_v>&& + r) noexcept(std::is_nothrow_invocable_v>&& std::is_nothrow_invocable_v< member_t, - callable_result_t< + std::invoke_result_t< member_t>&>&& is_nothrow_connectable_v< - callable_result_t< + std::invoke_result_t< member_t, - callable_result_t< + std::invoke_result_t< member_t>&>, remove_cvref_t>) { return operation( @@ -119,9 +119,9 @@ struct _operation::type { StateFactory stateFactory_; SuccessorFactory func_; - callable_result_t state_; + std::invoke_result_t state_; connect_result_t< - callable_result_t&>, + std::invoke_result_t&>, remove_cvref_t> innerOp_; }; @@ -129,12 +129,12 @@ struct _operation::type { namespace _cpo { struct _fn { template(typename StateFactory, typename SuccessorFactory) // - (requires callable> AND callable< + (requires std::is_invocable_v> AND std::is_invocable_v< std::decay_t, - callable_result_t>&> AND - sender>&> AND + sender, - callable_result_t>&>>) // + std::invoke_result_t>&>>) // auto operator()( StateFactory&& stateFactory, diff --git a/include/unifex/let_value_with_stop_source.hpp b/include/unifex/let_value_with_stop_source.hpp index 0fb9c6ed4..b21626e17 100644 --- a/include/unifex/let_value_with_stop_source.hpp +++ b/include/unifex/let_value_with_stop_source.hpp @@ -86,8 +86,8 @@ class _stop_source_receiver::type { Self, type>) // friend auto tag_invoke(CPO cpo, const Self& self) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return cpo(self.receiver_); } @@ -196,7 +196,7 @@ struct _stop_source_operation::type { UNIFEX_NO_UNIQUE_ADDRESS SuccessorFactory func_; UNIFEX_NO_UNIQUE_ADDRESS stop_token_type receiverToken_; UNIFEX_NO_UNIQUE_ADDRESS connect_result_t< - callable_result_t, + std::invoke_result_t, receiver_t> innerOp_; diff --git a/include/unifex/let_value_with_stop_token.hpp b/include/unifex/let_value_with_stop_token.hpp index 38552ebaf..5373acb1a 100644 --- a/include/unifex/let_value_with_stop_token.hpp +++ b/include/unifex/let_value_with_stop_token.hpp @@ -91,8 +91,8 @@ class _stop_token_receiver::type { (requires is_receiver_query_cpo_v // AND same_as) // friend auto tag_invoke(CPO cpo, const Self& self) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return cpo(self.receiver_); } @@ -101,7 +101,7 @@ class _stop_token_receiver::type { tag_t, const type& r, VisitFunc&& - func) noexcept(is_nothrow_callable_v) { + func) noexcept(std::is_nothrow_invocable_v) { func(r.receiver_); } diff --git a/include/unifex/manual_lifetime.hpp b/include/unifex/manual_lifetime.hpp index 7926eedfa..5aecdc559 100644 --- a/include/unifex/manual_lifetime.hpp +++ b/include/unifex/manual_lifetime.hpp @@ -44,9 +44,9 @@ class manual_lifetime { template [[maybe_unused]] T& - construct_with(Func&& func) noexcept(is_nothrow_callable_v) { + construct_with(Func&& func) noexcept(std::is_nothrow_invocable_v) { static_assert( - std::is_same_v, T>, + std::is_same_v, T>, "Return type of func() must be exactly T to permit copy-elision."); return *::new (static_cast(std::addressof(value_))) T(((Func &&) func)()); @@ -78,8 +78,8 @@ class manual_lifetime { template [[maybe_unused]] T& - construct_with(Func&& func) noexcept(is_nothrow_callable_v) { - static_assert(std::is_same_v, T&>); + construct_with(Func&& func) noexcept(std::is_nothrow_invocable_v) { + static_assert(std::is_same_v, T&>); value_ = std::addressof(((Func &&) func)()); return get(); } @@ -105,8 +105,8 @@ class manual_lifetime { template [[maybe_unused]] T&& - construct_with(Func&& func) noexcept(is_nothrow_callable_v) { - static_assert(std::is_same_v, T&&>); + construct_with(Func&& func) noexcept(std::is_nothrow_invocable_v) { + static_assert(std::is_same_v, T&&>); value_ = std::addressof(((Func &&) func)()); return get(); } @@ -127,8 +127,8 @@ class manual_lifetime { void construct() noexcept {} template - void construct_with(Func&& func) noexcept(is_nothrow_callable_v) { - static_assert(std::is_void_v>); + void construct_with(Func&& func) noexcept(std::is_nothrow_invocable_v) { + static_assert(std::is_void_v>); ((Func &&) func)(); } void destruct() noexcept {} @@ -162,7 +162,7 @@ inline void activate_union_member(manual_lifetime& box) noexcept { template [[maybe_unused]] // T& activate_union_member_with(manual_lifetime& box, Func&& func) noexcept( - is_nothrow_callable_v) { + std::is_nothrow_invocable_v) { auto* p = ::new (&box) manual_lifetime{}; scope_guard guard = [=]() noexcept { p->~manual_lifetime(); diff --git a/include/unifex/manual_lifetime_union.hpp b/include/unifex/manual_lifetime_union.hpp index 6ae48857a..3991de39f 100644 --- a/include/unifex/manual_lifetime_union.hpp +++ b/include/unifex/manual_lifetime_union.hpp @@ -40,7 +40,7 @@ class manual_lifetime_union { } template [[maybe_unused]] T& - construct_with(Func&& func) noexcept(is_nothrow_callable_v) { + construct_with(Func&& func) noexcept(std::is_nothrow_invocable_v) { return unifex::activate_union_member_with( *static_cast*>(static_cast(&storage_)), static_cast(func)); @@ -100,7 +100,7 @@ T& activate_union_member(manual_lifetime_union& box, Args&&... args) // template [[maybe_unused]] // T& activate_union_member_with(manual_lifetime_union& box, Func&& func) - noexcept(is_nothrow_callable_v) { + noexcept(std::is_nothrow_invocable_v) { auto* p = ::new (&box) manual_lifetime_union{}; scope_guard guard = [=]() noexcept { p->~manual_lifetime_union(); diff --git a/include/unifex/materialize.hpp b/include/unifex/materialize.hpp index d906e46f3..c7596b7d3 100644 --- a/include/unifex/materialize.hpp +++ b/include/unifex/materialize.hpp @@ -107,14 +107,14 @@ class _receiver::type { } template(typename CPO, UNIFEX_DECLARE_NON_DEDUCED_TYPE(R, type)) // - (requires is_receiver_query_cpo_v AND is_callable_v< + (requires is_receiver_query_cpo_v AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke( CPO cpo, const UNIFEX_USE_NON_DEDUCED_TYPE(R, type) & - r) noexcept(is_nothrow_callable_v) - -> callable_result_t { + r) noexcept(std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(std::as_const(r.receiver_)); } @@ -255,7 +255,7 @@ inline const struct _fn { return _mat::sender{(Source &&) source}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/nest.hpp b/include/unifex/nest.hpp index 8c4b48faa..6975278d6 100644 --- a/include/unifex/nest.hpp +++ b/include/unifex/nest.hpp @@ -61,7 +61,7 @@ inline const struct _nest_fn final { template constexpr auto operator()(Scope& scope) const - noexcept(is_nothrow_callable_v, deref, Scope*>) + noexcept(std::is_nothrow_invocable_v, deref, Scope*>) -> bind_back_result_t; } nest{}; @@ -76,7 +76,7 @@ struct _nest_fn::deref final { template inline constexpr auto _nest_fn::operator()(Scope& scope) const - noexcept(is_nothrow_callable_v, deref, Scope*>) + noexcept(std::is_nothrow_invocable_v, deref, Scope*>) -> bind_back_result_t { // bind_back will try to store a copy of any lvalue references it's passed, // which doesn't work for us here so we have to pass a scope pointer instead diff --git a/include/unifex/on_stream.hpp b/include/unifex/on_stream.hpp index bcdca77d2..d0e9af8c4 100644 --- a/include/unifex/on_stream.hpp +++ b/include/unifex/on_stream.hpp @@ -49,7 +49,7 @@ inline const struct _fn { (requires scheduler) // constexpr auto operator()(Scheduler&& scheduler) const - noexcept(is_nothrow_callable_v, _fn, Scheduler>) + noexcept(std::is_nothrow_invocable_v, _fn, Scheduler>) -> bind_back_result_t<_fn, Scheduler> { return bind_back(*this, (Scheduler &&) scheduler); } diff --git a/include/unifex/receiver_concepts.hpp b/include/unifex/receiver_concepts.hpp index 457759968..8a4af7b5c 100644 --- a/include/unifex/receiver_concepts.hpp +++ b/include/unifex/receiver_concepts.hpp @@ -241,18 +241,18 @@ UNIFEX_CONCEPT // template inline constexpr bool is_nothrow_receiver_of_v = - receiver_of&& is_nothrow_callable_v, R, An...>; + receiver_of&& std::is_nothrow_invocable_v, R, An...>; ////////////////// // Metafunctions for checking callability of specific receiver methods template inline constexpr bool is_next_receiver_v = - is_callable_v; + std::is_invocable_v; template inline constexpr bool is_nothrow_next_receiver_v = - is_nothrow_callable_v; + std::is_nothrow_invocable_v; } // namespace unifex diff --git a/include/unifex/reduce_stream.hpp b/include/unifex/reduce_stream.hpp index 5b5021b7d..8139036ce 100644 --- a/include/unifex/reduce_stream.hpp +++ b/include/unifex/reduce_stream.hpp @@ -105,8 +105,8 @@ struct _error_cleanup_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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -168,8 +168,8 @@ struct _done_cleanup_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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -223,8 +223,8 @@ struct _next_receiver::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -427,7 +427,7 @@ inline const struct _fn { } template constexpr auto operator()(State&& initialState, ReducerFunc&& reducer) const - noexcept(is_nothrow_callable_v, _fn, State, ReducerFunc>) + noexcept(std::is_nothrow_invocable_v, _fn, State, ReducerFunc>) -> bind_back_result_t<_fn, State, ReducerFunc> { return bind_back(*this, (State &&) initialState, (ReducerFunc &&) reducer); } diff --git a/include/unifex/repeat_effect_until.hpp b/include/unifex/repeat_effect_until.hpp index c16def764..6c7bbd5c4 100644 --- a/include/unifex/repeat_effect_until.hpp +++ b/include/unifex/repeat_effect_until.hpp @@ -115,12 +115,12 @@ class _rcvr::type { private: template(typename CPO) // - (requires is_receiver_query_cpo_v AND is_callable_v< + (requires is_receiver_query_cpo_v AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const type& r) noexcept( std::is_nothrow_invocable_v) - -> callable_result_t { + -> std::invoke_result_t { return std::move(cpo)(r.get_rcvr()); } @@ -299,7 +299,7 @@ inline const struct repeat_effect_until_cpo { } template constexpr auto operator()(Predicate&& predicate) const - noexcept(is_nothrow_callable_v< + noexcept(std::is_nothrow_invocable_v< tag_t, repeat_effect_until_cpo, Predicate>) @@ -332,7 +332,7 @@ inline const struct repeat_effect_cpo { (Source &&) source, forever{}}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, repeat_effect_cpo>) + noexcept(std::is_nothrow_invocable_v, repeat_effect_cpo>) -> bind_back_result_t { return bind_back(*this); } diff --git a/include/unifex/retry_when.hpp b/include/unifex/retry_when.hpp index fd1a2bdc4..45229d10b 100644 --- a/include/unifex/retry_when.hpp +++ b/include/unifex/retry_when.hpp @@ -124,10 +124,10 @@ class _trigger_receiver::type { private: template(typename CPO) // (requires is_receiver_query_cpo_v AND - is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const trigger_receiver& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -225,12 +225,12 @@ class _source_receiver::type { private: template(typename CPO) // - (requires is_receiver_query_cpo_v AND is_callable_v< + (requires is_receiver_query_cpo_v AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const source_receiver& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -456,7 +456,7 @@ inline const struct _fn { } template constexpr auto operator()(Func&& func) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&) func); } diff --git a/include/unifex/schedule_with_subscheduler.hpp b/include/unifex/schedule_with_subscheduler.hpp index dfe23dbdb..94fc5c16b 100644 --- a/include/unifex/schedule_with_subscheduler.hpp +++ b/include/unifex/schedule_with_subscheduler.hpp @@ -47,7 +47,7 @@ inline const struct _fn { template using _default_result_t = _then::sender< - callable_result_t, Scheduler&>, + std::invoke_result_t, Scheduler&>, _return_value>; template using _result_t = typename conditional_t< @@ -73,7 +73,7 @@ inline const struct _fn { static_cast(scheduleOp), {(Scheduler &&) sched}}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/sender_concepts.hpp b/include/unifex/sender_concepts.hpp index 74399a8fa..46addb076 100644 --- a/include/unifex/sender_concepts.hpp +++ b/include/unifex/sender_concepts.hpp @@ -307,11 +307,11 @@ using connect_result_t = template inline constexpr bool is_nothrow_connectable_v = - is_nothrow_callable_v, Sender, Receiver>; + std::is_nothrow_invocable_v, Sender, Receiver>; template using is_nothrow_connectable = - is_nothrow_callable, Sender, Receiver>; + std::is_nothrow_invocable, Sender, Receiver>; template < typename Sender, diff --git a/include/unifex/sender_for.hpp b/include/unifex/sender_for.hpp index 9ebd1a6ac..0fc344169 100644 --- a/include/unifex/sender_for.hpp +++ b/include/unifex/sender_for.hpp @@ -52,18 +52,18 @@ struct sender_for { // Forward all tag_invokes: template(typename CPO, typename Self, typename... Args) // (requires same_as> AND( - !callable) - AND callable, Args...>) // + !std::is_invocable_v) + AND std::is_invocable_v, Args...>) // UNIFEX_ALWAYS_INLINE friend decltype(auto) tag_invoke(CPO cpo, Self&& self, Args&&... args) noexcept( - is_nothrow_callable_v, Args...>) { + std::is_nothrow_invocable_v, Args...>) { return ((CPO &&) cpo)(((Self &&) self).snd_, (Args &&) args...); } // Handle custom property queries by consulting the context: template(typename CPO) // - (requires callable) // + (requires std::is_invocable_v) // UNIFEX_ALWAYS_INLINE friend decltype(auto) tag_invoke(CPO cpo, const sender_for& self) noexcept { diff --git a/include/unifex/sequence.hpp b/include/unifex/sequence.hpp index e88ca26a0..21a1b9d4a 100644 --- a/include/unifex/sequence.hpp +++ b/include/unifex/sequence.hpp @@ -67,25 +67,25 @@ class _successor_receiver::type final { private: template(typename CPO, typename R, typename... Args) // (requires is_receiver_cpo_v AND same_as AND - is_callable_v< + std::is_invocable_v< CPO, Receiver, Args...>) // friend auto tag_invoke(CPO cpo, R&& r, Args&&... args) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)( r.get_receiver_rvalue(), static_cast(args)...); } template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND - same_as AND is_callable_v< + same_as AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(r.get_const_receiver()); } @@ -173,12 +173,12 @@ class _predecessor_receiver::type final { private: template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND - same_as AND is_callable_v< + same_as AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return static_cast(cpo)(r.get_const_receiver()); } @@ -407,14 +407,14 @@ struct _fn { auto operator()(First&& first, Second&& second, Third&& third, Rest&&... rest) const noexcept( - is_nothrow_callable_v<_fn, First, Second>&& is_nothrow_callable_v< + std::is_nothrow_invocable_v<_fn, First, Second>&& std::is_nothrow_invocable_v< _fn, - callable_result_t<_fn, First, Second>, + std::invoke_result_t<_fn, First, Second>, Third, Rest...>) - -> callable_result_t< + -> std::invoke_result_t< _fn, - callable_result_t<_fn, First, Second>, + std::invoke_result_t<_fn, First, Second>, Third, Rest...> { // Fall-back to pair-wise invocation of the sequence() CPO. diff --git a/include/unifex/single.hpp b/include/unifex/single.hpp index daab3ed9a..53a71859a 100644 --- a/include/unifex/single.hpp +++ b/include/unifex/single.hpp @@ -153,7 +153,7 @@ inline const struct _fn { return _single::stream{(Sender &&) sender}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/spawn_detached.hpp b/include/unifex/spawn_detached.hpp index 092037789..151720c0a 100644 --- a/include/unifex/spawn_detached.hpp +++ b/include/unifex/spawn_detached.hpp @@ -158,7 +158,7 @@ struct _spawn_detached_fn { template > constexpr auto operator()(Scope& scope, const Alloc& alloc = {}) const noexcept( - is_nothrow_callable_v, deref, Scope*, const Alloc&>) + std::is_nothrow_invocable_v, deref, Scope*, const Alloc&>) -> std::enable_if_t< is_allocator_v, bind_back_result_t>; @@ -176,7 +176,7 @@ struct _spawn_detached_fn::deref final { template inline constexpr auto _spawn_detached_fn::operator()(Scope& scope, const Alloc& alloc) const noexcept( - is_nothrow_callable_v, deref, Scope*, const Alloc&>) + std::is_nothrow_invocable_v, deref, Scope*, const Alloc&>) -> std::enable_if_t< is_allocator_v, bind_back_result_t> { diff --git a/include/unifex/spawn_future.hpp b/include/unifex/spawn_future.hpp index 0cebd6780..136ea9dcc 100644 --- a/include/unifex/spawn_future.hpp +++ b/include/unifex/spawn_future.hpp @@ -792,9 +792,9 @@ struct [[nodiscard]] _future::type final { // constructs the Sender static auto make_sender(spawn_future_op_t* op) noexcept { - using callable = typename _future_sender_from_stop_token::type; + using invocable = typename _future_sender_from_stop_token::type; - return let_value_with_stop_token(callable{op}); + return let_value_with_stop_token(invocable{op}); } using sender_t = decltype(nest(make_sender(nullptr), UNIFEX_DECLVAL(Scope&))); @@ -991,7 +991,7 @@ struct _spawn_future_fn { template > constexpr auto operator()(Scope& scope, const Alloc& alloc = {}) const noexcept( - is_nothrow_callable_v, deref, Scope*, const Alloc&>) + std::is_nothrow_invocable_v, deref, Scope*, const Alloc&>) -> std::enable_if_t< is_allocator_v, bind_back_result_t>; @@ -1009,7 +1009,7 @@ struct _spawn_future_fn::deref final { template inline constexpr auto _spawn_future_fn::operator()(Scope& scope, const Alloc& alloc) const noexcept( - is_nothrow_callable_v, deref, Scope*, const Alloc&>) + std::is_nothrow_invocable_v, deref, Scope*, const Alloc&>) -> std::enable_if_t< is_allocator_v, bind_back_result_t> { diff --git a/include/unifex/std_concepts.hpp b/include/unifex/std_concepts.hpp index 49034a577..6d1c4d60e 100644 --- a/include/unifex/std_concepts.hpp +++ b/include/unifex/std_concepts.hpp @@ -231,11 +231,6 @@ UNIFEX_CONCEPT semiregular = copyable&& default_constructible; template UNIFEX_CONCEPT regular = semiregular&& equality_comparable; -template -UNIFEX_CONCEPT // - invocable = // - std::is_invocable_v; - } // namespace unifex #include diff --git a/include/unifex/stop_immediately.hpp b/include/unifex/stop_immediately.hpp index 55244c9e2..cf5fa1a92 100644 --- a/include/unifex/stop_immediately.hpp +++ b/include/unifex/stop_immediately.hpp @@ -457,7 +457,7 @@ struct _fn { source}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/stop_when.hpp b/include/unifex/stop_when.hpp index cf42d4ab1..748d2fbc9 100644 --- a/include/unifex/stop_when.hpp +++ b/include/unifex/stop_when.hpp @@ -92,8 +92,8 @@ class _srcvr::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -142,8 +142,8 @@ class _trcvr::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(r.get_receiver()); } @@ -406,7 +406,7 @@ struct _fn { } template constexpr auto operator()(Trigger&& trigger) const - noexcept(is_nothrow_callable_v, _fn, Trigger>) + noexcept(std::is_nothrow_invocable_v, _fn, Trigger>) -> bind_back_result_t<_fn, Trigger> { return bind_back(*this, (Trigger &&) trigger); } diff --git a/include/unifex/sync_wait.hpp b/include/unifex/sync_wait.hpp index 03a34afa8..37e532faf 100644 --- a/include/unifex/sync_wait.hpp +++ b/include/unifex/sync_wait.hpp @@ -146,7 +146,7 @@ struct _fn { return _sync_wait::_impl((Sender &&) sender); } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/take_until.hpp b/include/unifex/take_until.hpp index c0040b035..964cd6377 100644 --- a/include/unifex/take_until.hpp +++ b/include/unifex/take_until.hpp @@ -143,8 +143,8 @@ struct _stream::type { friend auto tag_invoke( CPO cpo, const receiver_wrapper& - r) noexcept(is_nothrow_callable_v) - -> callable_result_t { + r) noexcept(std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -247,8 +247,8 @@ struct _stream::type { friend auto tag_invoke( CPO cpo, const source_receiver& - r) noexcept(is_nothrow_callable_v) - -> callable_result_t { + r) noexcept(std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -288,8 +288,8 @@ struct _stream::type { friend auto tag_invoke( CPO cpo, const trigger_receiver& - r) noexcept(is_nothrow_callable_v) - -> callable_result_t { + r) noexcept(std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.op_.receiver_)); } @@ -499,7 +499,7 @@ inline const struct _fn { } template constexpr auto operator()(TriggerStream&& trigger) const - noexcept(is_nothrow_callable_v, _fn, TriggerStream>) + noexcept(std::is_nothrow_invocable_v, _fn, TriggerStream>) -> bind_back_result_t<_fn, TriggerStream> { return bind_back(*this, (TriggerStream &&) trigger); } diff --git a/include/unifex/then.hpp b/include/unifex/then.hpp index 24f963b73..64b9dafc6 100644 --- a/include/unifex/then.hpp +++ b/include/unifex/then.hpp @@ -105,8 +105,8 @@ struct _receiver::type { template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND same_as) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.receiver_)); } @@ -230,7 +230,7 @@ struct _fn { } template constexpr auto operator()(Func&& func) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&) func); } diff --git a/include/unifex/transform_stream.hpp b/include/unifex/transform_stream.hpp index f9b1a4b06..ede6d624c 100644 --- a/include/unifex/transform_stream.hpp +++ b/include/unifex/transform_stream.hpp @@ -36,7 +36,7 @@ struct _fn { } template constexpr auto operator()(Func&& func) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&) func); } diff --git a/include/unifex/type_erased_stream.hpp b/include/unifex/type_erased_stream.hpp index 81da95bfc..17a7aee0d 100644 --- a/include/unifex/type_erased_stream.hpp +++ b/include/unifex/type_erased_stream.hpp @@ -465,7 +465,7 @@ struct _fn final { return _type_erase::stream{(Stream &&) strm}; } constexpr auto operator()() const - noexcept(is_nothrow_callable_v, _fn>) + noexcept(std::is_nothrow_invocable_v, _fn>) -> bind_back_result_t<_fn> { return bind_back(*this); } diff --git a/include/unifex/type_traits.hpp b/include/unifex/type_traits.hpp index 6e842ca15..8f9f45e4c 100644 --- a/include/unifex/type_traits.hpp +++ b/include/unifex/type_traits.hpp @@ -220,71 +220,6 @@ struct decayed_tuple { template inline constexpr bool is_one_of_v = (UNIFEX_IS_SAME(T, Ts) || ...); -template -using callable_result_t = - decltype(UNIFEX_DECLVAL(Fn &&)(UNIFEX_DECLVAL(As &&)...)); - -namespace _is_callable { -struct yes_type { - char dummy; -}; -struct no_type { - char dummy[2]; -}; -static_assert(sizeof(yes_type) != sizeof(no_type)); - -template > -yes_type _try_call(Fn (*)(As...)) noexcept( - noexcept(UNIFEX_DECLVAL(Fn&&)(UNIFEX_DECLVAL(As&&)...))); -no_type _try_call(...) noexcept(false); -} // namespace _is_callable - -template -inline constexpr bool - is_callable_v = sizeof(decltype(_is_callable::_try_call( - static_cast(nullptr)))) == - sizeof(_is_callable::yes_type); - -template -struct is_callable : std::bool_constant> {}; - -template -inline constexpr bool _is_callable_r_v = false; - -template -inline constexpr bool _is_callable_r_v = - std::is_convertible_v, R>; - -template -inline constexpr bool is_callable_r_v = - _is_callable_r_v, R, Fn, As...>; - -template -struct is_callable_r : std::bool_constant> {}; - -template -inline constexpr bool is_nothrow_callable_v = - noexcept(_is_callable::_try_call(static_cast(nullptr))); - -template -struct is_nothrow_callable - : std::bool_constant> {}; - -template -inline constexpr bool _is_nothrow_callable_r_v = false; - -template -inline constexpr bool _is_nothrow_callable_r_v = - is_nothrow_convertible, R>::value; - -template -inline constexpr bool is_nothrow_callable_r_v = - _is_nothrow_callable_r_v, R, Fn, As...>; - -template -struct is_nothrow_callable_r - : std::bool_constant> {}; - template struct is_allocator : std::false_type {}; diff --git a/include/unifex/upon_done.hpp b/include/unifex/upon_done.hpp index 9d5bf5757..312b1f2d6 100644 --- a/include/unifex/upon_done.hpp +++ b/include/unifex/upon_done.hpp @@ -91,8 +91,8 @@ struct _receiver::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return (CPO &&)(cpo)(std::as_const(r.receiver_)); } @@ -220,7 +220,7 @@ struct _fn { public: template(typename Sender, typename Func) // - (requires invocable AND tag_invocable<_fn, Sender, Func>) // + (requires std::is_invocable_v AND tag_invocable<_fn, Sender, Func>) // auto operator()(Sender&& predecessor, Func&& func) const noexcept(is_nothrow_tag_invocable_v<_fn, Sender, Func>) @@ -229,7 +229,7 @@ struct _fn { } template(typename Sender, typename Func) // - (requires(!tag_invocable<_fn, Sender, Func>) AND invocable) // + (requires(!tag_invocable<_fn, Sender, Func>) AND std::is_invocable_v) // auto operator()(Sender&& predecessor, Func&& func) const noexcept(std::is_nothrow_constructible_v< @@ -240,10 +240,10 @@ struct _fn { (Sender &&)(predecessor), (Func &&)(func)}; } template(typename Func) // - (requires invocable) // + (requires std::is_invocable_v) // constexpr auto operator()(Func&& func) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&)(func)); } diff --git a/include/unifex/upon_error.hpp b/include/unifex/upon_error.hpp index b76e6648b..a310cee65 100644 --- a/include/unifex/upon_error.hpp +++ b/include/unifex/upon_error.hpp @@ -91,8 +91,8 @@ struct _receiver::type { 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 { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return (CPO &&)(cpo)(std::as_const(r.receiver_)); } @@ -221,7 +221,7 @@ struct _fn { template constexpr auto operator()(Func&& func) const - noexcept(is_nothrow_callable_v, _fn, Func>) + noexcept(std::is_nothrow_invocable_v, _fn, Func>) -> bind_back_result_t<_fn, Func> { return bind_back(*this, (Func &&)(func)); } diff --git a/include/unifex/v0/async_scope.hpp b/include/unifex/v0/async_scope.hpp index 5026f833c..f147c6bd6 100644 --- a/include/unifex/v0/async_scope.hpp +++ b/include/unifex/v0/async_scope.hpp @@ -169,11 +169,11 @@ struct async_scope { } template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // void spawn_call_on(Scheduler&& scheduler, Fun&& fun) { static_assert( - is_nothrow_callable_v, - "Please annotate your callable with noexcept."); + std::is_nothrow_invocable_v, + "Please annotate your invocable with noexcept."); spawn_on((Scheduler &&) scheduler, just_from((Fun &&) fun)); } diff --git a/include/unifex/v1/async_scope.hpp b/include/unifex/v1/async_scope.hpp index 1d06887bb..96f612f5d 100644 --- a/include/unifex/v1/async_scope.hpp +++ b/include/unifex/v1/async_scope.hpp @@ -314,7 +314,7 @@ struct async_scope { * Equivalent to spawn_on((Scheduler&&)scheduler, just_from((Fun&&)fun)). */ template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // auto spawn_call_on(Scheduler&& scheduler, Fun&& fun) { return spawn_on((Scheduler &&) scheduler, just_from((Fun &&) fun)); } @@ -348,11 +348,11 @@ struct async_scope { * just_from((Fun&&)fun)). */ template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // void detached_spawn_call_on(Scheduler&& scheduler, Fun&& fun) { static_assert( - is_nothrow_callable_v, - "Please annotate your callable with noexcept."); + std::is_nothrow_invocable_v, + "Please annotate your invocable with noexcept."); detached_spawn_on((Scheduler &&) scheduler, just_from((Fun &&) fun)); } @@ -378,7 +378,7 @@ struct async_scope { * Equivalent to attach(just_from((Fun&&)fun)). */ template(typename Fun) // - (requires callable) // + (requires std::is_invocable_v) // [[nodiscard]] auto attach_call(Fun&& fun) noexcept( noexcept(attach(just_from((Fun &&) fun)))) { return attach(just_from((Fun &&) fun)); @@ -398,7 +398,7 @@ struct async_scope { * Equivalent to attach_on((Scheduler&&)scheduler, just_from((Fun&&)fun)). */ template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // [[nodiscard]] auto attach_call_on(Scheduler&& scheduler, Fun&& fun) noexcept( noexcept( attach_on((Scheduler &&) scheduler, just_from((Fun &&) fun)))) { diff --git a/include/unifex/v1/debug_async_scope.hpp b/include/unifex/v1/debug_async_scope.hpp index e58201bf5..ab480360e 100644 --- a/include/unifex/v1/debug_async_scope.hpp +++ b/include/unifex/v1/debug_async_scope.hpp @@ -44,7 +44,7 @@ struct debug_async_scope final { } template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // auto spawn_call_on(Scheduler&& scheduler, Fun&& fun) { return spawn_on( static_cast(scheduler), @@ -64,11 +64,11 @@ struct debug_async_scope final { } template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // void detached_spawn_call_on(Scheduler&& scheduler, Fun&& fun) { static_assert( - is_nothrow_callable_v, - "Please annotate your callable with noexcept."); + std::is_nothrow_invocable_v, + "Please annotate your invocable with noexcept."); detached_spawn_on( static_cast(scheduler), @@ -90,7 +90,7 @@ struct debug_async_scope final { } template(typename Fun) // - (requires callable) // + (requires std::is_invocable_v) // [[nodiscard]] auto attach_call(Fun&& fun) noexcept( noexcept(attach(just_from(static_cast(fun))))) { return attach(just_from(static_cast(fun))); @@ -107,7 +107,7 @@ struct debug_async_scope final { } template(typename Scheduler, typename Fun) // - (requires scheduler AND callable) // + (requires scheduler AND std::is_invocable_v) // [[nodiscard]] auto attach_call_on(Scheduler&& scheduler, Fun&& fun) noexcept( noexcept(attach_on( static_cast(scheduler), diff --git a/include/unifex/via.hpp b/include/unifex/via.hpp index 4a7a09fe7..4e0f8ac84 100644 --- a/include/unifex/via.hpp +++ b/include/unifex/via.hpp @@ -57,7 +57,7 @@ struct _fn { (requires scheduler) // constexpr auto operator()(Scheduler&& scheduler) const - noexcept(is_nothrow_callable_v, _fn, Scheduler>) + noexcept(std::is_nothrow_invocable_v, _fn, Scheduler>) -> bind_back_result_t<_fn, Scheduler> { return bind_back(*this, (Scheduler &&) scheduler); } diff --git a/include/unifex/via_stream.hpp b/include/unifex/via_stream.hpp index 2a0e13a61..79ddb27ad 100644 --- a/include/unifex/via_stream.hpp +++ b/include/unifex/via_stream.hpp @@ -48,7 +48,7 @@ struct _fn { (requires scheduler) // constexpr auto operator()(Scheduler&& scheduler) const - noexcept(is_nothrow_callable_v, _fn, Scheduler>) + noexcept(std::is_nothrow_invocable_v, _fn, Scheduler>) -> bind_back_result_t<_fn, Scheduler> { return bind_back(*this, (Scheduler &&) scheduler); } diff --git a/include/unifex/when_all.hpp b/include/unifex/when_all.hpp index bb8bb8f08..f47486707 100644 --- a/include/unifex/when_all.hpp +++ b/include/unifex/when_all.hpp @@ -176,12 +176,12 @@ struct _element_receiver::type final { template(typename CPO, typename R) // (requires is_receiver_query_cpo_v AND - same_as AND is_callable_v< + same_as AND std::is_invocable_v< CPO, const Receiver&>) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - is_nothrow_callable_v) - -> callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.get_receiver())); } diff --git a/include/unifex/when_all_range.hpp b/include/unifex/when_all_range.hpp index 9ee4dd9af..dbc48d6fc 100644 --- a/include/unifex/when_all_range.hpp +++ b/include/unifex/when_all_range.hpp @@ -235,10 +235,10 @@ struct _element_receiver::type final { template(typename CPO, typename R) // (requires unifex::is_receiver_query_cpo_v AND unifex::same_as AND - unifex::is_callable_v) // + std::is_invocable_v) // friend auto tag_invoke(CPO cpo, const R& r) noexcept( - unifex::is_nothrow_callable_v) - -> unifex::callable_result_t { + std::is_nothrow_invocable_v) + -> std::invoke_result_t { return std::move(cpo)(std::as_const(r.get_receiver())); } diff --git a/include/unifex/win32/low_latency_iocp_context.hpp b/include/unifex/win32/low_latency_iocp_context.hpp index d0c59067d..ab5929a14 100644 --- a/include/unifex/win32/low_latency_iocp_context.hpp +++ b/include/unifex/win32/low_latency_iocp_context.hpp @@ -361,7 +361,7 @@ class low_latency_iocp_context::_schedule_op::type } } - if constexpr (is_nothrow_callable_v, Receiver>) { + if constexpr (std::is_nothrow_invocable_v, Receiver>) { unifex::set_value(std::move(self.receiver_)); } else { UNIFEX_TRY { unifex::set_value(std::move(self.receiver_)); } @@ -505,7 +505,7 @@ class low_latency_iocp_context::_read_file_op::type // TODO: Should we be sending tuple of (bytesTransferred, ec) here // instead? if (!ec || totalBytesTransferred > 0) { - if constexpr (is_nothrow_callable_v< + if constexpr (std::is_nothrow_invocable_v< tag_t, Receiver, std::size_t>) { @@ -683,7 +683,7 @@ class low_latency_iocp_context::_write_file_op::type // TODO: Should we be sending tuple of (bytesTransferred, ec) here // instead? if (!ec || totalBytesTransferred > 0) { - if constexpr (is_nothrow_callable_v< + if constexpr (std::is_nothrow_invocable_v< tag_t, Receiver, std::size_t>) { diff --git a/include/unifex/win32/windows_thread_pool.hpp b/include/unifex/win32/windows_thread_pool.hpp index b4fb7fc89..1231db042 100644 --- a/include/unifex/win32/windows_thread_pool.hpp +++ b/include/unifex/win32/windows_thread_pool.hpp @@ -161,7 +161,7 @@ class windows_thread_pool::_schedule_op::type final static void CALLBACK work_callback(PTP_CALLBACK_INSTANCE, void* workContext, PTP_WORK) noexcept { auto& op = *static_cast(workContext); - if constexpr (is_nothrow_callable_v< + if constexpr (std::is_nothrow_invocable_v< decltype(unifex::set_value), Receiver>) { unifex::set_value(std::move(op.receiver_)); @@ -419,7 +419,7 @@ class windows_thread_pool::_cancellable_schedule_op::type final private: void set_value_impl() noexcept override { - if constexpr (is_nothrow_callable_v< + if constexpr (std::is_nothrow_invocable_v< decltype(unifex::set_value), Receiver>) { unifex::set_value(std::move(receiver_)); @@ -703,7 +703,7 @@ class windows_thread_pool::_schedule_at_op::type final private: void set_value_impl() noexcept override { - if constexpr (unifex::is_nothrow_callable_v< + if constexpr (std::is_nothrow_invocable_v< decltype(unifex::set_value), Receiver>) { unifex::set_value(std::move(receiver_)); @@ -791,7 +791,7 @@ class windows_thread_pool::_schedule_after_op::type final private: void set_value_impl() noexcept override { - if constexpr (unifex::is_nothrow_callable_v< + if constexpr (std::is_nothrow_invocable_v< decltype(unifex::set_value), Receiver>) { unifex::set_value(std::move(receiver_)); diff --git a/include/unifex/with_allocator.hpp b/include/unifex/with_allocator.hpp index 6252303c3..24b86714c 100644 --- a/include/unifex/with_allocator.hpp +++ b/include/unifex/with_allocator.hpp @@ -30,7 +30,7 @@ struct _fn { } template constexpr auto operator()(Allocator&& allocator) const - noexcept(is_nothrow_callable_v, _fn, Allocator>) + noexcept(std::is_nothrow_invocable_v, _fn, Allocator>) -> bind_back_result_t<_fn, Allocator> { return bind_back(*this, (Allocator &&) allocator); } diff --git a/include/unifex/with_query_value.hpp b/include/unifex/with_query_value.hpp index 6b0e5c761..d23f25890 100644 --- a/include/unifex/with_query_value.hpp +++ b/include/unifex/with_query_value.hpp @@ -48,13 +48,13 @@ class _receiver_wrapper::type { } template(typename OtherCPO, typename Self, typename... Args) // - (requires same_as, type> AND callable< + (requires same_as, type> AND std::is_invocable_v< OtherCPO, member_t, Args...>) // friend auto tag_invoke(OtherCPO cpo, Self&& self, Args&&... args) noexcept( - is_nothrow_callable_v, Args...>) - -> callable_result_t, Args...> { + std::is_nothrow_invocable_v, Args...>) + -> std::invoke_result_t, Args...> { return static_cast(cpo)( static_cast(self).receiver_, static_cast(args)...); } @@ -176,7 +176,7 @@ inline const struct _fn { } template constexpr auto operator()(const CPO&, Value&& value) const - noexcept(is_nothrow_callable_v, _fn, CPO, Value>) + noexcept(std::is_nothrow_invocable_v, _fn, CPO, Value>) -> bind_back_result_t<_fn, CPO, Value> { return bind_back(*this, CPO{}, (Value &&) value); } diff --git a/test/any_object_test.cpp b/test/any_object_test.cpp index bdc13debc..c8f3b129e 100644 --- a/test/any_object_test.cpp +++ b/test/any_object_test.cpp @@ -340,7 +340,7 @@ static_assert(std::is_convertible_v); static_assert(!std::is_convertible_v); // Some other checks about the nature of the type-erased wrapper. -static_assert(unifex::callable); +static_assert(std::is_invocable_v); static_assert(std::is_nothrow_move_constructible_v); static_assert(!std::is_copy_constructible_v); diff --git a/test/let_value_with_stop_token_test.cpp b/test/let_value_with_stop_token_test.cpp index 8aac705c3..36fddc877 100644 --- a/test/let_value_with_stop_token_test.cpp +++ b/test/let_value_with_stop_token_test.cpp @@ -121,7 +121,7 @@ TEST_F(LetWithStopToken, InplaceStoppableStopSourceMayThrow) { }); }; static_assert(!is_nothrow_connectable_v< - callable_result_t< + std::invoke_result_t< decltype(let_value_with_stop_source), decltype(stopSourceFunctor)>, InplaceStoppableIntReceiver>); @@ -155,7 +155,7 @@ TEST_F(LetWithStopToken, InplaceStoppableStopSourceNoexcept) { }); }; static_assert(is_nothrow_connectable_v< - callable_result_t< + std::invoke_result_t< decltype(let_value_with_stop_source), decltype(stopSourceFunctor)>, InplaceStoppableIntReceiver>); @@ -190,7 +190,7 @@ TEST_F(LetWithStopToken, InplaceStoppableMayThrow) { }); }; static_assert(!is_nothrow_connectable_v< - callable_result_t< + std::invoke_result_t< decltype(let_value_with_stop_token), decltype(stop_token_functor)>, InplaceStoppableIntReceiver>); @@ -224,7 +224,7 @@ TEST_F(LetWithStopToken, InplaceStoppableNoexcept) { }); }; static_assert(is_nothrow_connectable_v< - callable_result_t< + std::invoke_result_t< decltype(let_value_with_stop_token), decltype(stop_token_functor)>, InplaceStoppableIntReceiver>); @@ -356,7 +356,7 @@ TEST_F(LetWithStopToken, PreserveOperationStateUnstoppable) { return destructionCountingLetValueWithStopToken(stopSource); }; static_assert(is_nothrow_connectable_v< - callable_result_t< + std::invoke_result_t< decltype(let_value_with_stop_source), decltype(stopSourceFunctor)>, UnstoppableSimpleIntReceiver>); From 9061c47d48d94d2603d2a8edb646e5c7d012a31b Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Thu, 11 Apr 2024 17:34:21 -0700 Subject: [PATCH 2/3] Use ASSERT_TRUE with optional/expected type has_value assertions These assertions are usually followed by other expressions assuming that they are passing and in case a change breaks them they potentially trigger undefined behavior with `EXCEPT_TRUE`. --- test/awaitable_senders_test.cpp | 4 ++-- test/into_variant_test.cpp | 6 +++--- test/let_done_test.cpp | 4 ++-- test/let_error_test.cpp | 6 +++--- test/on_test.cpp | 4 ++-- test/schedule_with_subsceduler_test.cpp | 4 ++-- test/stop_when_test.cpp | 2 +- test/task_scheduler_affinity_test.cpp | 4 ++-- test/unstoppable_test.cpp | 2 +- test/when_all_2_test.cpp | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/awaitable_senders_test.cpp b/test/awaitable_senders_test.cpp index e615050b7..5472ae3f0 100644 --- a/test/awaitable_senders_test.cpp +++ b/test/awaitable_senders_test.cpp @@ -41,7 +41,7 @@ TEST(awaitable_senders, non_void) { std::optional answer = sync_wait(makeTask()); - EXPECT_TRUE(answer.has_value()); + ASSERT_TRUE(answer.has_value()); EXPECT_EQ(42, *answer); } @@ -70,7 +70,7 @@ TEST(awaitable_senders, void) { std::optional answer = sync_wait(makeTask()); - EXPECT_TRUE(answer.has_value()); + ASSERT_TRUE(answer.has_value()); } TEST(awaitable_senders, task_cancellation) { diff --git a/test/into_variant_test.cpp b/test/into_variant_test.cpp index 334e409a0..867bace3b 100644 --- a/test/into_variant_test.cpp +++ b/test/into_variant_test.cpp @@ -84,7 +84,7 @@ TEST(IntoVariant, Working) { return d + 1; })))); EXPECT_TRUE(called); - EXPECT_TRUE(x.has_value()); + ASSERT_TRUE(x.has_value()); const auto& [vt_first_val, vt_second_val] = std::get<0>(x.value()); const auto& [first_val] = std::get<0>(vt_first_val); const auto [second_val] = std::get<0>(vt_second_val); @@ -100,7 +100,7 @@ TEST(IntoVariant, Pipeable) { })) | into_variant() | sync_wait(); EXPECT_TRUE(called); - EXPECT_TRUE(x.has_value()); + ASSERT_TRUE(x.has_value()); const auto& [vt_first_val, vt_second_val] = std::get<0>(x.value()); const auto& [first_val] = std::get<0>(vt_first_val); const auto [second_val] = std::get<0>(vt_second_val); @@ -116,7 +116,7 @@ TEST(IntoVariant, OneOfPossibleValues) { }) | into_variant() | sync_wait(); EXPECT_FALSE(called); - EXPECT_TRUE(x.has_value()); + ASSERT_TRUE(x.has_value()); const auto& [val] = std::get<0>(x.value()); EXPECT_EQ(val, 42); } diff --git a/test/let_done_test.cpp b/test/let_done_test.cpp index 3f1f208f7..fc4b9bd9e 100644 --- a/test/let_done_test.cpp +++ b/test/let_done_test.cpp @@ -84,12 +84,12 @@ TEST(TransformDone, Pipeable) { TEST(TransformDone, WithValue) { auto one = just_done() | let_done([] { return just(42); }) | sync_wait(); - EXPECT_TRUE(one.has_value()); + ASSERT_TRUE(one.has_value()); EXPECT_EQ(*one, 42); auto multiple = just_done() | let_done([] { return just(42, 1, 2); }) | sync_wait(); - EXPECT_TRUE(multiple.has_value()); + ASSERT_TRUE(multiple.has_value()); EXPECT_EQ(*multiple, std::tuple(42, 1, 2)); } diff --git a/test/let_error_test.cpp b/test/let_error_test.cpp index 158717388..bba48a655 100644 --- a/test/let_error_test.cpp +++ b/test/let_error_test.cpp @@ -185,7 +185,7 @@ TEST(TransformError, WithTask) { | let_done([]() { return just(-2); }) // | sync_wait(); - EXPECT_TRUE(value.has_value()); + ASSERT_TRUE(value.has_value()); EXPECT_EQ(*value, 42); # if !UNIFEX_NO_EXCEPTIONS @@ -200,7 +200,7 @@ TEST(TransformError, WithTask) { | let_done([]() { return just(-2); }) // | sync_wait(); - EXPECT_TRUE(error.has_value()); + ASSERT_TRUE(error.has_value()); EXPECT_EQ(*error, -1); # endif // !UNIFEX_NO_EXCEPTIONS @@ -215,7 +215,7 @@ TEST(TransformError, WithTask) { | let_done([]() { return just(-2); }) // | sync_wait(); - EXPECT_TRUE(done.has_value()); + ASSERT_TRUE(done.has_value()); EXPECT_EQ(*done, -2); } #endif // !UNIFEX_NO_COROUTINES diff --git a/test/on_test.cpp b/test/on_test.cpp index 1364ffa5c..6e5db04e9 100644 --- a/test/on_test.cpp +++ b/test/on_test.cpp @@ -66,7 +66,7 @@ TEST(On, Smoke) { }))); EXPECT_NE(id1, id2); EXPECT_EQ(id2, thread.get_thread_id()); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); } TEST(On, Tag) { @@ -77,5 +77,5 @@ TEST(On, Tag) { auto result = sync_wait(on(thread.get_scheduler(), c)); EXPECT_NE(id1, c.id2); EXPECT_EQ(c.id2, thread.get_thread_id()); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); } diff --git a/test/schedule_with_subsceduler_test.cpp b/test/schedule_with_subsceduler_test.cpp index 0b9eb5dec..7b70771e5 100644 --- a/test/schedule_with_subsceduler_test.cpp +++ b/test/schedule_with_subsceduler_test.cpp @@ -30,7 +30,7 @@ TEST(schedule_with_subscheduler, Smoke) { schedule_with_subscheduler(scheduler), [&](auto subScheduler) noexcept { return subScheduler == scheduler; })); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); EXPECT_TRUE(result.value()); } @@ -44,6 +44,6 @@ TEST(schedule_with_subscheduler, Pipeable) { }) | sync_wait(); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); EXPECT_TRUE(result.value()); } diff --git a/test/stop_when_test.cpp b/test/stop_when_test.cpp index ebfe5cd4d..342afa322 100644 --- a/test/stop_when_test.cpp +++ b/test/stop_when_test.cpp @@ -54,7 +54,7 @@ TEST(StopWhen, SourceCompletesFirst) { unifex::then( unifex::schedule_after(1s), [&] { triggerExecuted = true; })))); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); EXPECT_EQ(42, result.value()); EXPECT_TRUE(sourceExecuted); diff --git a/test/task_scheduler_affinity_test.cpp b/test/task_scheduler_affinity_test.cpp index 7f9f8e772..b10e1f28a 100644 --- a/test/task_scheduler_affinity_test.cpp +++ b/test/task_scheduler_affinity_test.cpp @@ -220,7 +220,7 @@ TEST_F( auto ret = unifex::sync_wait( unifex::let_value_with_stop_source(awaitSenderThatIgnoresDone)); - EXPECT_TRUE(ret.has_value()); + ASSERT_TRUE(ret.has_value()); } namespace { @@ -295,7 +295,7 @@ TEST_F( auto ret = unifex::sync_wait( unifex::let_value_with_stop_source(awaitAwaitableThatIgnoresDone)); - EXPECT_TRUE(ret.has_value()); + ASSERT_TRUE(ret.has_value()); } namespace { diff --git a/test/unstoppable_test.cpp b/test/unstoppable_test.cpp index 4adb48c44..b438e8144 100644 --- a/test/unstoppable_test.cpp +++ b/test/unstoppable_test.cpp @@ -34,5 +34,5 @@ TEST(Unstoppable, Smoke) { return unstoppable(on(thread.get_scheduler(), just())); })); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); } diff --git a/test/when_all_2_test.cpp b/test/when_all_2_test.cpp index 600a139ce..7f38c00f7 100644 --- a/test/when_all_2_test.cpp +++ b/test/when_all_2_test.cpp @@ -194,7 +194,7 @@ TEST(WhenAll2, ResultsAreDecayCopied) { std::variant>>> result = sync_wait( when_all(string_const_ref_sender{}, string_const_ref_sender{})); - EXPECT_TRUE(result.has_value()); + ASSERT_TRUE(result.has_value()); EXPECT_EQ( "hello world", std::get<0>(std::get<0>(std::get<0>(result.value())))); EXPECT_EQ( From 22bcfd1e806df7f51696170819bc9d9bf0c0e6f3 Mon Sep 17 00:00:00 2001 From: Deniz Evrenci Date: Thu, 11 Apr 2024 11:50:24 -0700 Subject: [PATCH 3/3] Add support for function references (free and static member) in bind_back The following program does not compile: https://godbolt.org/z/WfhEc51dY But if we replace the function reference with a lambda, it does: https://godbolt.org/z/jrhTY4nse Constructing a std::tuple with a function type fails but function pointers are allowed. We instantiate _result with std::decay_t... which maps function references to function pointers and then the corresponding std::tuple instantiation does not fail to compile. The problem with the existing code is that, in order to instantiate std::tuple...>, we first constructed a std::tuple and passed it over. If instead we construct a std::tuple...> with the function arguments, they will be converted to function pointers and the std::tuple instantiation will compile. --- include/unifex/bind_back.hpp | 6 +++-- test/let_done_test.cpp | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/include/unifex/bind_back.hpp b/include/unifex/bind_back.hpp index 2cf87e61b..ae4c0e9e1 100644 --- a/include/unifex/bind_back.hpp +++ b/include/unifex/bind_back.hpp @@ -137,10 +137,12 @@ inline const struct _fn { template constexpr auto operator()(Cpo cpo, ArgN&&... argN) const noexcept(noexcept(_result...>{ - {}, (Cpo &&) cpo, std::tuple{(ArgN &&) argN...}})) + {}, + (Cpo &&) cpo, + std::tuple...>{(ArgN &&) argN...}})) -> _result...> { return _result...>{ - {}, (Cpo &&) cpo, std::tuple{(ArgN &&) argN...}}; + {}, (Cpo &&) cpo, std::tuple...>{(ArgN &&) argN...}}; } } bind_back{}; diff --git a/test/let_done_test.cpp b/test/let_done_test.cpp index fc4b9bd9e..571425b07 100644 --- a/test/let_done_test.cpp +++ b/test/let_done_test.cpp @@ -93,3 +93,52 @@ TEST(TransformDone, WithValue) { ASSERT_TRUE(multiple.has_value()); EXPECT_EQ(*multiple, std::tuple(42, 1, 2)); } + +static auto just42() { + return just(42); +} + +TEST(TransformDone, WithFunction) { + auto freeFunction = just_done() | let_done(just42) | sync_wait(); + + ASSERT_TRUE(freeFunction.has_value()); + EXPECT_EQ(*freeFunction, 42); + + struct StaticMemberFunction { + static auto call() { return just(42, 1, 2); } + }; + + auto staticMemberFunction = + just_done() | let_done(StaticMemberFunction::call) | sync_wait(); + + ASSERT_TRUE(staticMemberFunction.has_value()); + EXPECT_EQ(*staticMemberFunction, std::tuple(42, 1, 2)); +} + +TEST(TransformDone, WithExplicitCopyMove) { + struct ExplicitCopy { + ExplicitCopy() = default; + + explicit ExplicitCopy(const ExplicitCopy& other) = default; + + auto operator()() { return just(42, 1, 2); } + }; + + auto explicitCopy = just_done() | let_done(ExplicitCopy{}) | sync_wait(); + + ASSERT_TRUE(explicitCopy.has_value()); + EXPECT_EQ(*explicitCopy, std::tuple(42, 1, 2)); + + struct ExplicitMove { + ExplicitMove() = default; + + explicit ExplicitMove(ExplicitMove&& other) = default; + + auto operator()() { return just(42, 1, 2); } + }; + + auto explicitMove = just_done() | let_done(ExplicitMove{}) | sync_wait(); + + ASSERT_TRUE(explicitMove.has_value()); + EXPECT_EQ(*explicitMove, std::tuple(42, 1, 2)); +}