-
Notifications
You must be signed in to change notification settings - Fork 190
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
Update finally to support value channel references #545
Changes from 4 commits
9feb969
472130c
2bb4f83
6a722c6
e2453cc
ab1811d
913eaf6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -24,7 +24,26 @@ | |||||
namespace unifex { | ||||||
namespace _create { | ||||||
|
||||||
template <typename Receiver, typename Fn, typename Context> | ||||||
template <typename From, typename To, typename = void> | ||||||
struct _do_convert { | ||||||
To operator()(From&&) = delete; | ||||||
}; | ||||||
|
||||||
template <typename From> | ||||||
struct _do_convert<From, From, void> { | ||||||
From&& operator()(From&& obj) noexcept { | ||||||
return static_cast<From&&>(obj); | ||||||
} | ||||||
}; | ||||||
|
||||||
template <typename From, typename To> | ||||||
struct _do_convert<From, To, std::void_t<std::enable_if_t<convertible_to<From, To>>>> { | ||||||
To operator()(From&& obj) { | ||||||
return static_cast<From&&>(obj); | ||||||
} | ||||||
}; | ||||||
|
||||||
template <typename Receiver, typename Fn, typename Context, typename... ValueTypes> | ||||||
struct _op { | ||||||
struct type { | ||||||
explicit type(Receiver rec, Fn fn, Context ctx) | ||||||
|
@@ -34,9 +53,18 @@ struct _op { | |||||
: rec_((Receiver&&) rec), fn_((Fn&&) fn), ctx_((Context&&) ctx) {} | ||||||
|
||||||
template (typename... Ts) | ||||||
(requires receiver_of<Receiver, Ts...>) | ||||||
void set_value(Ts&&... ts) noexcept(is_nothrow_receiver_of_v<Receiver, Ts...>) { | ||||||
unifex::set_value((Receiver&&) rec_, (Ts&&) ts...); | ||||||
(requires receiver_of<Receiver, Ts...> AND (convertible_to<Ts, ValueTypes> && ...)) | ||||||
ccotter marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
void set_value(Ts&&... ts) noexcept { | ||||||
UNIFEX_TRY { | ||||||
// Satisfy the value completion contract with _do_convert, which | ||||||
// ensures the value passed to the receiver conforms to | ||||||
// the value types of the create sender. For example, if set_value | ||||||
// is called with an lvalue reference but create sends non-reference | ||||||
// values, _do_convert decays the provided Ts. | ||||||
unifex::set_value(std::move(rec_), _do_convert<Ts&&, ValueTypes>{}(static_cast<Ts&&>(ts))...); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we've agreed on an implementation of
Suggested change
If it's the same behaviour, do you see value in the different spelling? I might be convinced that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes, |
||||||
} UNIFEX_CATCH(...) { | ||||||
unifex::set_error(std::move(rec_), std::current_exception()); | ||||||
} | ||||||
} | ||||||
|
||||||
template (typename Error) | ||||||
|
@@ -79,10 +107,10 @@ struct _op { | |||||
}; | ||||||
}; | ||||||
|
||||||
template <typename Receiver, typename Fn, typename Context> | ||||||
using _operation = typename _op<Receiver, Fn, Context>::type; | ||||||
template <typename Receiver, typename Fn, typename Context, typename... ValueTypes> | ||||||
using _operation = typename _op<Receiver, Fn, Context, ValueTypes...>::type; | ||||||
|
||||||
template <typename Fn, typename Context> | ||||||
template <typename Fn, typename Context, typename... ValueTypes> | ||||||
struct _snd_base { | ||||||
struct type { | ||||||
template <template<typename...> class Variant> | ||||||
|
@@ -101,14 +129,14 @@ struct _snd_base { | |||||
(requires derived_from<remove_cvref_t<Self>, type> AND | ||||||
constructible_from<Fn, member_t<Self, Fn>> AND | ||||||
constructible_from<Context, member_t<Self, Context>>) | ||||||
ccotter marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
friend _operation<remove_cvref_t<Receiver>, Fn, Context> | ||||||
friend _operation<remove_cvref_t<Receiver>, Fn, Context, ValueTypes...> | ||||||
tag_invoke(tag_t<connect>, Self&& self, Receiver&& rec) | ||||||
noexcept(std::is_nothrow_constructible_v< | ||||||
_operation<Receiver, Fn, Context>, | ||||||
_operation<Receiver, Fn, Context, ValueTypes...>, | ||||||
Receiver, | ||||||
member_t<Self, Fn>, | ||||||
member_t<Self, Context>>) { | ||||||
return _operation<remove_cvref_t<Receiver>, Fn, Context>{ | ||||||
return _operation<remove_cvref_t<Receiver>, Fn, Context, ValueTypes...>{ | ||||||
(Receiver&&) rec, | ||||||
((Self&&) self).fn_, | ||||||
((Self&&) self).ctx_}; | ||||||
|
@@ -121,7 +149,7 @@ struct _snd_base { | |||||
|
||||||
template <typename Fn, typename Context, typename... ValueTypes> | ||||||
struct _snd { | ||||||
struct type : _snd_base<Fn, Context>::type { | ||||||
struct type : _snd_base<Fn, Context, ValueTypes...>::type { | ||||||
template <template<typename...> class Variant, template <typename...> class Tuple> | ||||||
using value_types = Variant<Tuple<ValueTypes...>>; | ||||||
}; | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the
void_t
is redundant here; I would expectenable_if_t
to already aliasvoid
when the condition is true.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code ran into ambiguous template error when From=To (e.g.,
do_convert<int&,int&>
), andvoid_t
appeared to make this template more specialization, but to be honest, I am not great with SFINAE in this case. What did end up working wasstd::enable_if_t<!std::is_same_v<From, To> && convertible_to<From, To>>
without thevoid_t
.Unsurprisingly, a C++20 constraints version worked with just
template <typename From, typename To> requires convertible_to<From, To> struct _do_convert<From, To> { ...
In any case, I don't think we need
_do_convert
.