Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for function references (free and static member) in bind_back #605

Merged
merged 3 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/unifex/allocate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ inline const struct _fn {
return _alloc::sender<Sender>{(Sender &&) predecessor};
}
constexpr auto operator()() const
noexcept(is_nothrow_callable_v<tag_t<bind_back>, _fn>)
noexcept(std::is_nothrow_invocable_v<tag_t<bind_back>, _fn>)
-> bind_back_result_t<_fn> {
return bind_back(*this);
}
Expand Down
4 changes: 2 additions & 2 deletions include/unifex/any_scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ struct _with<CPOs...>::any_scheduler {

template(typename Receiver) //
(requires receiver_of<Receiver> AND(
invocable<CPOs, const Receiver&>&&...)) //
std::is_invocable_v<CPOs, const Receiver&>&&...)) //
any_operation_state_for<Receiver> connect(Receiver rec) && {
any_scheduler_impl<CPOs...> const& impl = sched_.impl_;
return any_operation_state_for<Receiver>{
Expand Down Expand Up @@ -281,7 +281,7 @@ struct _with<CPOs...>::any_scheduler_ref {

template(typename Receiver) //
(requires receiver_of<Receiver> AND(
invocable<CPOs, const Receiver&>&&...)) //
std::is_invocable_v<CPOs, const Receiver&>&&...)) //
any_operation_state_for<Receiver> connect(Receiver rec) && {
any_scheduler_ref_impl<CPOs...> const& impl = sched_.impl_;
return any_operation_state_for<Receiver>{
Expand Down
12 changes: 6 additions & 6 deletions include/unifex/any_sender_of.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,20 +174,20 @@ struct _op_for<Receiver>::type {
// to the receiver after unsubscribing the stop token.
template(typename CPO, typename... Args) //
(requires is_receiver_cpo_v<CPO> AND
is_callable_v<CPO, Receiver, Args...>) //
std::is_invocable_v<CPO, Receiver, Args...>) //
friend void tag_invoke(CPO cpo, type&& self, Args&&... args) noexcept(
is_nothrow_callable_v<CPO, Receiver, Args...>) {
std::is_nothrow_invocable_v<CPO, Receiver, Args...>) {
self.subscription_.unsubscribe();
cpo(std::move(self).rec_, (Args &&) args...);
}

// Forward other receiver queries
template(typename CPO) //
(requires is_receiver_query_cpo_v<CPO> AND
is_callable_v<CPO, const Receiver&>) //
std::is_invocable_v<CPO, const Receiver&>) //
friend auto tag_invoke(CPO cpo, const type& self) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
std::is_nothrow_invocable_v<CPO, const Receiver&>)
-> std::invoke_result_t<CPO, const Receiver&> {
return std::move(cpo)(self.rec_);
}

Expand Down Expand Up @@ -238,7 +238,7 @@ struct _with<CPOs...>::_sender<Values...>::type

template(typename Receiver) //
(requires receiver_of<Receiver, Values...> AND(
invocable<CPOs, Receiver const&>&&...)) //
std::is_invocable_v<CPOs, Receiver const&>&&...)) //
_operation_state_for<Receiver> connect(Receiver r) && {
any_unique_t<_connect<type_list<CPOs...>, Values...>>& self = *this;
return _operation_state_for<Receiver>{
Expand Down
8 changes: 4 additions & 4 deletions include/unifex/at_coroutine_exit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ struct _die_on_done_rec {

template(typename CPO) //
(requires is_receiver_query_cpo_v<CPO> AND
is_callable_v<CPO, const Receiver&>) //
std::is_invocable_v<CPO, const Receiver&>) //
friend auto tag_invoke(CPO cpo, const type& p) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
std::is_nothrow_invocable_v<CPO, const Receiver&>)
-> std::invoke_result_t<CPO, const Receiver&> {
return cpo(p.rec_);
}
};
Expand Down Expand Up @@ -313,7 +313,7 @@ inline constexpr struct _fn {

public:
template(typename Action, typename... Ts) //
(requires callable<std::decay_t<Action>, std::decay_t<Ts>...>) //
(requires std::is_invocable_v<std::decay_t<Action>, std::decay_t<Ts>...>) //
_cleanup_task<std::decay_t<Ts>...>
operator()(Action&& action, Ts&&... ts) const {
return _fn::at_coroutine_exit((Action &&) action, (Ts &&) ts...);
Expand Down
6 changes: 3 additions & 3 deletions include/unifex/await_transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ struct _awaitable_base<Promise, Value>::type {

template(typename CPO) //
(requires is_receiver_query_cpo_v<CPO> AND
is_callable_v<CPO, const Promise&>) //
std::is_invocable_v<CPO, const Promise&>) //
friend auto tag_invoke(CPO cpo, const _rec& r) noexcept(
is_nothrow_callable_v<CPO, const Promise&>)
-> callable_result_t<CPO, const Promise&> {
std::is_nothrow_invocable_v<CPO, const Promise&>)
-> std::invoke_result_t<CPO, const Promise&> {
const Promise& p = r.continuation_.promise();
return std::move(cpo)(p);
}
Expand Down
30 changes: 16 additions & 14 deletions include/unifex/bind_back.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ namespace _compose {
struct _fn {
template <typename Target, typename Other, typename Self>
auto operator()(Target&& target, Other&& other, Self&& self) const noexcept(
is_nothrow_callable_v<Other, Target>&&
is_nothrow_callable_v<Self, callable_result_t<Other, Target>>)
-> callable_result_t<Self, callable_result_t<Other, Target>> {
std::is_nothrow_invocable_v<Other, Target>&&
std::is_nothrow_invocable_v<Self, std::invoke_result_t<Other, Target>>)
-> std::invoke_result_t<Self, std::invoke_result_t<Other, Target>> {
return ((Self &&) self)(((Other &&) other)((Target &&) target));
}
};
Expand All @@ -56,11 +56,11 @@ struct _apply_fn_impl<Cpo, Target>::type {
Target&& target_;

template(typename... ArgN) //
(requires callable<Cpo, Target, ArgN...>) //
(requires std::is_invocable_v<Cpo, Target, ArgN...>) //
auto
operator()(ArgN&&... argN) noexcept(
is_nothrow_callable_v<Cpo, Target, ArgN...>)
-> callable_result_t<Cpo, Target, ArgN...> {
std::is_nothrow_invocable_v<Cpo, Target, ArgN...>)
-> std::invoke_result_t<Cpo, Target, ArgN...> {
return ((Cpo &&) cpo_)((Target &&) target_, (ArgN &&) argN...);
}
};
Expand All @@ -82,19 +82,19 @@ struct _result_impl<Cpo, ArgN...>::type : _result_base {

template(typename Target) //
(requires(!derived_from<remove_cvref_t<Target>, _result_base>)
AND callable<Cpo const&, Target, ArgN const&...>) //
AND std::is_invocable_v<Cpo const&, Target, ArgN const&...>) //
decltype(auto)
operator()(Target&& target) const& noexcept(
is_nothrow_callable_v<Cpo const&, Target, ArgN const&...>) {
std::is_nothrow_invocable_v<Cpo const&, Target, ArgN const&...>) {
return std::apply(
_apply_fn<Cpo const&, Target>{cpo_, (Target &&) target}, argN_);
}
template(typename Target) //
(requires(!derived_from<remove_cvref_t<Target>, _result_base>)
AND callable<Cpo, Target, ArgN...>) //
AND std::is_invocable_v<Cpo, Target, ArgN...>) //
decltype(auto)
operator()(Target&& target) && noexcept(
is_nothrow_callable_v<Cpo, Target, ArgN...>) {
std::is_nothrow_invocable_v<Cpo, Target, ArgN...>) {
return std::apply(
_apply_fn<Cpo, Target>{(Cpo &&) cpo_, (Target &&) target},
std::move(argN_));
Expand All @@ -104,10 +104,10 @@ struct _result_impl<Cpo, ArgN...>::type : _result_base {
(requires(!derived_from<
remove_cvref_t<Target>,
_result_base>) AND same_as<remove_cvref_t<Self>, type> AND
callable<member_t<Self, Cpo>, Target, member_t<Self, ArgN>...>) //
std::is_invocable_v<member_t<Self, Cpo>, Target, member_t<Self, ArgN>...>) //
friend decltype(auto)
operator|(Target&& target, Self&& self) noexcept(
is_nothrow_callable_v<
std::is_nothrow_invocable_v<
member_t<Self, Cpo>,
Target,
member_t<Self, ArgN>...>) {
Expand Down Expand Up @@ -137,10 +137,12 @@ inline const struct _fn {
template <typename Cpo, typename... ArgN>
constexpr auto operator()(Cpo cpo, ArgN&&... argN) const
noexcept(noexcept(_result<Cpo, std::decay_t<ArgN>...>{
{}, (Cpo &&) cpo, std::tuple{(ArgN &&) argN...}}))
{},
(Cpo &&) cpo,
std::tuple<std::decay_t<ArgN>...>{(ArgN &&) argN...}}))
-> _result<Cpo, std::decay_t<ArgN>...> {
return _result<Cpo, std::decay_t<ArgN>...>{
{}, (Cpo &&) cpo, std::tuple{(ArgN &&) argN...}};
{}, (Cpo &&) cpo, std::tuple<std::decay_t<ArgN>...>{(ArgN &&) argN...}};
}
} bind_back{};

Expand Down
6 changes: 3 additions & 3 deletions include/unifex/bulk_join.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ class _join_receiver<Receiver>::type {
Self,
type>) //
friend auto tag_invoke(CPO cpo, const Self& self) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
std::is_nothrow_invocable_v<CPO, const Receiver&>)
-> std::invoke_result_t<CPO, const Receiver&> {
return cpo(self.receiver_);
}

Expand Down Expand Up @@ -166,7 +166,7 @@ struct _fn {
return join_sender<remove_cvref_t<Source>>{(Source &&) source};
}
constexpr auto operator()() const
noexcept(is_nothrow_callable_v<tag_t<bind_back>, _fn>)
noexcept(std::is_nothrow_invocable_v<tag_t<bind_back>, _fn>)
-> bind_back_result_t<_fn> {
return bind_back(*this);
}
Expand Down
2 changes: 1 addition & 1 deletion include/unifex/bulk_schedule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ struct _fn {
}
template <typename Integral>
constexpr auto operator()(Integral n) const
noexcept(is_nothrow_callable_v<tag_t<bind_back>, _fn, Integral>)
noexcept(std::is_nothrow_invocable_v<tag_t<bind_back>, _fn, Integral>)
-> bind_back_result_t<_fn, Integral> {
return bind_back(*this, n);
}
Expand Down
16 changes: 8 additions & 8 deletions include/unifex/bulk_transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class _tfx_receiver<Func, Policy, Receiver>::type {
, policy_(std::move(policy)) {}

template(typename... Values) //
(requires invocable<Func&, Values...> AND
(requires std::is_invocable_v<Func&, Values...> AND
std::is_void_v<std::invoke_result_t<
Func&,
Values...>>) //
Expand All @@ -59,7 +59,7 @@ class _tfx_receiver<Func, Policy, Receiver>::type {
}

template(typename... Values) //
(requires invocable<Func&, Values...> AND(
(requires std::is_invocable_v<Func&, Values...> AND(
!std::is_void_v<std::invoke_result_t<
Func&,
Values...>>)) //
Expand Down Expand Up @@ -115,8 +115,8 @@ class _tfx_receiver<Func, Policy, Receiver>::type {
Self,
type>) //
friend auto tag_invoke(CPO cpo, const Self& self) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
std::is_nothrow_invocable_v<CPO, const Receiver&>)
-> std::invoke_result_t<CPO, const Receiver&> {
return cpo(self.receiver_);
}

Expand Down Expand Up @@ -238,8 +238,8 @@ struct _fn {
(requires bulk_sender<Source>) //
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));
}

Expand Down Expand Up @@ -271,13 +271,13 @@ struct _fn {
}
template <typename Func>
constexpr auto operator()(Func&& f) const
noexcept(is_nothrow_callable_v<tag_t<bind_back>, _fn, Func>)
noexcept(std::is_nothrow_invocable_v<tag_t<bind_back>, _fn, Func>)
-> bind_back_result_t<_fn, Func> {
return bind_back(*this, (Func &&) f);
}
template <typename Func, typename FuncPolicy>
constexpr auto operator()(Func&& f, FuncPolicy policy) const
noexcept(is_nothrow_callable_v<tag_t<bind_back>, _fn, Func, FuncPolicy>)
noexcept(std::is_nothrow_invocable_v<tag_t<bind_back>, _fn, Func, FuncPolicy>)
-> bind_back_result_t<_fn, Func, FuncPolicy> {
return bind_back(*this, (Func &&) f, (FuncPolicy &&) policy);
}
Expand Down
4 changes: 2 additions & 2 deletions include/unifex/config.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
// class foo_sender {
// template<
// typename Receiver,
// std::enable_if_t<is_callable_v<tag_t<set_value>, Receiver, foo>, int> = 0>
// std::enable_if_t<std::is_invocable_v<tag_t<set_value>, Receiver, foo>, int> = 0>
// friend auto tag_invoke(tag_t<connect>, foo_sender&& s, Receiver&& r) -> foo_operation<Receiver> {
// return ...;
// }
Expand All @@ -139,7 +139,7 @@
// typename Receiver,
// UNIFEX_DECLARE_NON_DEDUCED_TYPE(CPO, tag_t<connect>),
// UNIFEX_DECLARE_NON_DEDUCED_TYPE(S, foo_sender),
// std::enable_if_t<is_callable_v<tag_t<set_value>, Receiver, foo>, int> = 0?
// std::enable_if_t<std::is_invocable_v<tag_t<set_value>, Receiver, foo>, int> = 0?
// friend auto tag_invoke(
// UNIFEX_USE_NON_DEDUCED_TYPE(CPO, tag_t<connect>),
// UNIFEX_USE_NON_DEDUCED_TYPE(S, foo_sender)&& s,
Expand Down
8 changes: 4 additions & 4 deletions include/unifex/connect_awaitable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ class _sender_task<Receiver>::type {

template(typename CPO) //
(requires is_receiver_query_cpo_v<CPO> AND
is_callable_v<CPO, const Receiver&>) //
std::is_invocable_v<CPO, const Receiver&>) //
friend auto tag_invoke(CPO cpo, const promise_type& p) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
std::is_nothrow_invocable_v<CPO, const Receiver&>)
-> std::invoke_result_t<CPO, const Receiver&> {
return cpo(std::as_const(p.receiver_));
}

Expand Down Expand Up @@ -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<Receiver>::promise_type;
using awaitable_type = callable_result_t<
using awaitable_type = std::invoke_result_t<
tag_t<unifex::await_transform>,
promise_type&,
Awaitable>;
Expand Down
4 changes: 2 additions & 2 deletions include/unifex/continuations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ namespace _visit_continuations_cpo {
inline const struct _fn {
#if !UNIFEX_NO_COROUTINES
template(typename Promise, typename Func) //
(requires(!same_as<Promise, void>) AND callable<_fn, Promise&, Func>) //
(requires(!same_as<Promise, void>) AND std::is_invocable_v<_fn, Promise&, Func>) //
friend void tag_invoke(
_fn cpo,
coro::coroutine_handle<Promise> 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
Expand Down
8 changes: 4 additions & 4 deletions include/unifex/create.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ struct _op {
// Forward other receiver queries
template(typename CPO) //
(requires is_receiver_query_cpo_v<CPO> AND
is_callable_v<CPO, const Receiver&>) //
std::is_invocable_v<CPO, const Receiver&>) //
friend auto tag_invoke(CPO cpo, const type& self) noexcept(
is_nothrow_callable_v<CPO, const Receiver&>)
-> callable_result_t<CPO, const Receiver&> {
std::is_nothrow_invocable_v<CPO, const Receiver&>)
-> std::invoke_result_t<CPO, const Receiver&> {
return std::move(cpo)(self.rec_);
}

Expand Down Expand Up @@ -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<ValueTypes...> concept. This function should dispatch to
* the C-style callback (see example). \param[in] ctx An optional extra bit of
Expand Down
8 changes: 4 additions & 4 deletions include/unifex/defer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ namespace unifex {
namespace _defer {
inline const struct _fn {
template(typename Callable)(
requires callable<Callable> AND
sender<callable_result_t<Callable>>) constexpr auto
operator()(Callable&& callable) const {
return let_value(just(), (Callable &&) callable);
requires std::is_invocable_v<Callable> AND
sender<std::invoke_result_t<Callable>>) constexpr auto
operator()(Callable&& invocable) const {
return let_value(just(), (Callable &&) invocable);
}
} defer{};
} // namespace _defer
Expand Down
2 changes: 1 addition & 1 deletion include/unifex/delay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ inline const struct _fn {
template <typename Scheduler, typename Duration>
constexpr auto operator()(Scheduler&& scheduler, Duration&& duration) const
noexcept(
is_nothrow_callable_v<tag_t<bind_back>, _fn, Scheduler, Duration>)
std::is_nothrow_invocable_v<tag_t<bind_back>, _fn, Scheduler, Duration>)
-> bind_back_result_t<_fn, Scheduler, Duration> {
return bind_back(*this, (Scheduler &&) scheduler, (Duration &&) duration);
}
Expand Down
Loading
Loading