Skip to content

Commit 2674beb

Browse files
authored
Merge pull request #1571 from ericniebler/un-tag-invoke-sequence-senders
make it possible to define a sequence sender without using `tag_invoke`
2 parents 9f93762 + b5ec460 commit 2674beb

File tree

7 files changed

+92
-125
lines changed

7 files changed

+92
-125
lines changed

include/exec/__detail/__basic_sequence.hpp

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -71,31 +71,18 @@ namespace exec {
7171
return {};
7272
}
7373

74-
template <
75-
stdexec::same_as<get_item_types_t> _Tag,
76-
stdexec::__decays_to<__seqexpr> _Self,
77-
class _Env
78-
>
79-
friend auto tag_invoke(_Tag, _Self&& __self, _Env&& __env) -> stdexec::__msecond<
80-
stdexec::__if_c<stdexec::same_as<_Tag, get_item_types_t>>,
81-
decltype(__self.__tag()
82-
.get_item_types(static_cast<_Self&&>(__self), static_cast<_Env&&>(__env)))
83-
> {
74+
template <stdexec::__decays_to<__seqexpr> _Self, class _Env>
75+
STDEXEC_MEMFN_DECL(auto get_item_types)(this _Self&& __self, _Env&& __env)
76+
-> decltype(__self.__tag()
77+
.get_item_types(static_cast<_Self&&>(__self), static_cast<_Env&&>(__env))) {
8478
return {};
8579
}
8680

87-
template <
88-
stdexec::same_as<subscribe_t> _Tag,
89-
stdexec::__decays_to<__seqexpr> _Self,
90-
/*receiver*/ class _Receiver
91-
>
92-
friend auto tag_invoke(_Tag, _Self&& __self, _Receiver&& __rcvr) noexcept(noexcept(
81+
template <stdexec::__decays_to<__seqexpr> _Self, stdexec::receiver _Receiver>
82+
STDEXEC_MEMFN_DECL(auto subscribe)(this _Self&& __self, _Receiver&& __rcvr) noexcept(noexcept(
9383
__self.__tag().subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr))))
94-
-> stdexec::__msecond<
95-
stdexec::__if_c<stdexec::same_as<_Tag, subscribe_t>>,
96-
decltype(__self.__tag()
97-
.subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr)))
98-
> {
84+
-> decltype(__self.__tag()
85+
.subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr))) {
9986
return __tag_t::subscribe(static_cast<_Self&&>(__self), static_cast<_Receiver&&>(__rcvr));
10087
}
10188

@@ -104,13 +91,11 @@ namespace exec {
10491
apply(_Sender&& __sndr, _ApplyFn&& __fun) noexcept(stdexec::__nothrow_callable<
10592
stdexec::__detail::__impl_of<_Sender>,
10693
stdexec::__copy_cvref_fn<_Sender>,
107-
_ApplyFn
108-
>)
94+
_ApplyFn>)
10995
-> stdexec::__call_result_t<
11096
stdexec::__detail::__impl_of<_Sender>,
11197
stdexec::__copy_cvref_fn<_Sender>,
112-
_ApplyFn
113-
> {
98+
_ApplyFn> {
11499
return static_cast<_Sender&&>(__sndr)
115100
.__impl_(stdexec::__copy_cvref_fn<_Sender>(), static_cast<_ApplyFn&&>(__fun));
116101
}

include/exec/any_sender_of.hpp

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,7 @@ namespace exec {
249249
class _Allocator,
250250
bool _Copyable = false,
251251
std::size_t _InlineSize = 3 * sizeof(void*),
252-
std::size_t _Alignment = alignof(std::max_align_t)
253-
>
252+
std::size_t _Alignment = alignof(std::max_align_t)>
254253
struct __storage {
255254
class __t;
256255
};
@@ -259,8 +258,7 @@ namespace exec {
259258
class _Vtable,
260259
class _Allocator,
261260
std::size_t _InlineSize = 3 * sizeof(void*),
262-
std::size_t _Alignment = alignof(std::max_align_t)
263-
>
261+
std::size_t _Alignment = alignof(std::max_align_t)>
264262
struct __immovable_storage {
265263
class __t : __immovable {
266264
static constexpr std::size_t __buffer_size = std::max(_InlineSize, sizeof(void*));
@@ -378,8 +376,7 @@ namespace exec {
378376
class _Allocator,
379377
bool _Copyable,
380378
std::size_t _InlineSize,
381-
std::size_t _Alignment
382-
>
379+
std::size_t _Alignment>
383380
class __storage<_Vtable, _Allocator, _Copyable, _InlineSize, _Alignment>::__t
384381
: __if_c<_Copyable, __, __move_only> {
385382
static_assert(
@@ -398,8 +395,7 @@ namespace exec {
398395
using __vtable_t = __if_c<
399396
_Copyable,
400397
__storage_vtable<_Vtable, __with_delete, __with_move, __with_copy>,
401-
__storage_vtable<_Vtable, __with_delete, __with_move>
402-
>;
398+
__storage_vtable<_Vtable, __with_delete, __with_move>>;
403399

404400
template <class _Tp>
405401
static constexpr auto __get_vtable_of_type() noexcept -> const __vtable_t* {
@@ -410,8 +406,7 @@ namespace exec {
410406
_Vtable,
411407
__with_delete,
412408
__with_move,
413-
__with_copy
414-
>;
409+
__with_copy>;
415410
} else {
416411
return &__storage_vtbl<__t, __decay_t<_Tp>, _Vtable, __with_delete, __with_move>;
417412
}
@@ -446,8 +441,8 @@ namespace exec {
446441
}
447442

448443
__t(const __t& __other)
449-
requires(_Copyable) : __vtable_(__other.__vtable_)
450-
{
444+
requires(_Copyable)
445+
: __vtable_(__other.__vtable_) {
451446
(*__other.__vtable_)(__copy_construct, this, __other);
452447
}
453448

@@ -461,7 +456,8 @@ namespace exec {
461456
return *this;
462457
}
463458

464-
__t(__t&& __other) noexcept : __vtable_(__other.__vtable_) {
459+
__t(__t&& __other) noexcept
460+
: __vtable_(__other.__vtable_) {
465461
(*__other.__vtable_)(__move_construct, this, static_cast<__t&&>(__other));
466462
}
467463

@@ -587,8 +583,7 @@ namespace exec {
587583
class _VTable = __empty_vtable,
588584
class _Allocator = std::allocator<std::byte>,
589585
std::size_t _InlineSize = 3 * sizeof(void*),
590-
std::size_t _Alignment = alignof(std::max_align_t)
591-
>
586+
std::size_t _Alignment = alignof(std::max_align_t)>
592587
using __immovable_storage_t =
593588
__t<__immovable_storage<_VTable, _Allocator, _InlineSize, _Alignment>>;
594589

@@ -598,8 +593,7 @@ namespace exec {
598593
template <
599594
class _VTable,
600595
std::size_t _InlineSize = 3 * sizeof(void*),
601-
class _Allocator = std::allocator<std::byte>
602-
>
596+
class _Allocator = std::allocator<std::byte>>
603597
using __copyable_storage_t = __t<__storage<_VTable, _Allocator, true, _InlineSize>>;
604598

605599
template <class _Tag, class... _As>
@@ -743,8 +737,7 @@ namespace exec {
743737
using _FilteredQueries =
744738
__minvoke<__mremove_if<__q<__is_never_stop_token_query>>, _Queries...>;
745739
using __vtable_t = stdexec::__t<
746-
__mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>, _FilteredQueries>
747-
>;
740+
__mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>, _FilteredQueries>>;
748741

749742
struct __env_t {
750743
const __vtable_t* __vtable_;
@@ -835,8 +828,7 @@ namespace exec {
835828
STDEXEC_ATTRIBUTE(no_unique_address) _Receiver __rcvr_;
836829
stdexec::inplace_stop_source __stop_source_{};
837830
using __stop_callback = typename stdexec::stop_token_of_t<
838-
stdexec::env_of_t<_Receiver>
839-
>::template callback_type<__on_stop_t>;
831+
stdexec::env_of_t<_Receiver>>::template callback_type<__on_stop_t>;
840832
std::optional<__stop_callback> __on_stop_{};
841833
};
842834

@@ -851,11 +843,12 @@ namespace exec {
851843
using receiver_concept = stdexec::receiver_t;
852844
__operation_base<_Receiver>* __op_;
853845

854-
template <same_as<__t> _Self, class _Item>
846+
template <class _Item>
855847
requires __callable<set_next_t, _Receiver&, _Item>
856-
STDEXEC_MEMFN_DECL(auto set_next)(this _Self& __self, _Item&& __item) noexcept
848+
[[nodiscard]]
849+
auto set_next(_Item&& __item) & noexcept(__nothrow_callable<set_next_t, _Receiver&, _Item>)
857850
-> __call_result_t<set_next_t, _Receiver&, _Item> {
858-
return exec::set_next(__self.__op_->__rcvr_, static_cast<_Item&&>(__item));
851+
return exec::set_next(__op_->__rcvr_, static_cast<_Item&&>(__item));
859852
}
860853

861854
template <class... _Args>
@@ -1045,8 +1038,7 @@ namespace exec {
10451038

10461039
template <receiver_of<_Sigs> _Rcvr>
10471040
auto connect(_Rcvr __rcvr) && -> stdexec::__t<
1048-
__operation<stdexec::__id<_Rcvr>, __with_inplace_stop_token>
1049-
> {
1041+
__operation<stdexec::__id<_Rcvr>, __with_inplace_stop_token>> {
10501042
return {static_cast<__t&&>(*this), static_cast<_Rcvr&&>(__rcvr)};
10511043
}
10521044

@@ -1197,8 +1189,7 @@ namespace exec {
11971189
template <auto... _SenderQueries>
11981190
class any_sender {
11991191
using __sender_base = stdexec::__t<
1200-
__any::__sender<_Completions, queries<_SenderQueries...>, queries<_ReceiverQueries...>>
1201-
>;
1192+
__any::__sender<_Completions, queries<_SenderQueries...>, queries<_ReceiverQueries...>>>;
12021193
__sender_base __sender_;
12031194

12041195
template <class _Tag, stdexec::__decays_to<any_sender> Self, class... _As>
@@ -1229,8 +1220,7 @@ namespace exec {
12291220
// Add the required set_value_t() completions to the schedule-sender.
12301221
using __schedule_completions = stdexec::__concat_completion_signatures<
12311222
_Completions,
1232-
stdexec::completion_signatures<stdexec::set_value_t()>
1233-
>;
1223+
stdexec::completion_signatures<stdexec::set_value_t()>>;
12341224
using __schedule_receiver = any_receiver_ref<__schedule_completions, _ReceiverQueries...>;
12351225

12361226
template <typename _Tag, typename _Sig>
@@ -1245,10 +1235,8 @@ namespace exec {
12451235

12461236
using __schedule_sender_queries = stdexec::__minvoke<
12471237
stdexec::__mremove_if<
1248-
__ret_equals_to<stdexec::get_completion_scheduler_t<stdexec::set_value_t>>
1249-
>,
1250-
decltype(_SenderQueries)...
1251-
>;
1238+
__ret_equals_to<stdexec::get_completion_scheduler_t<stdexec::set_value_t>>>,
1239+
decltype(_SenderQueries)...>;
12521240

12531241
#if STDEXEC_MSVC()
12541242
// MSVCBUG https://developercommunity.visualstudio.com/t/ICE-and-non-ICE-bug-in-NTTP-argument-w/10361081
@@ -1261,8 +1249,7 @@ namespace exec {
12611249
#else
12621250
template <class... _Queries>
12631251
using __schedule_sender_fn = typename __schedule_receiver::template any_sender<
1264-
stdexec::get_completion_scheduler<stdexec::set_value_t>.template signature<any_scheduler() noexcept>
1265-
>;
1252+
stdexec::get_completion_scheduler<stdexec::set_value_t>.template signature<any_scheduler() noexcept>>;
12661253
#endif
12671254
using __schedule_sender =
12681255
stdexec::__mapply<stdexec::__q<__schedule_sender_fn>, __schedule_sender_queries>;

include/exec/sequence/any_sequence_of.hpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,13 @@ namespace exec {
300300
return stdexec::get_env(__receiver_);
301301
}
302302

303-
private:
304-
STDEXEC_MEMFN_FRIEND(set_value);
305-
STDEXEC_MEMFN_FRIEND(set_error);
306-
STDEXEC_MEMFN_FRIEND(set_stopped);
307-
308-
template <std::same_as<__t> _Self, stdexec::sender _Sender>
309-
requires stdexec::__callable<set_next_t, _Self&, _Sender>
310-
STDEXEC_MEMFN_DECL(auto set_next)(this _Self& __self, _Sender&& __sender) {
311-
return exec::set_next(__self.__receiver_, static_cast<_Sender&&>(__sender));
303+
template <stdexec::sender _Item>
304+
requires stdexec::__callable<set_next_t, __receiver_base&, _Item>
305+
[[nodiscard]]
306+
auto set_next(_Item&& __item) & noexcept(
307+
stdexec::__nothrow_callable<set_next_t, __receiver_base&, _Item>)
308+
-> stdexec::__call_result_t<set_next_t, __receiver_base&, _Item> {
309+
return exec::set_next(__receiver_, static_cast<_Item&&>(__item));
312310
}
313311

314312
void set_value() noexcept
@@ -337,8 +335,7 @@ namespace exec {
337335
using __sender_base = stdexec::__t<__any::__sequence_sender<
338336
_Completions,
339337
queries<_SenderQueries...>,
340-
queries<_ReceiverQueries...>
341-
>>;
338+
queries<_ReceiverQueries...>>>;
342339
__sender_base __sender_;
343340

344341
public:

include/exec/sequence/ignore_all_values.hpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ namespace exec {
9797
_ResultVariant,
9898
__decayed_std_tuple<set_error_t, _Error>,
9999
set_error_t,
100-
_Error
101-
>
100+
_Error>
102101
&& __callable<stdexec::set_stopped_t, _ItemReceiver>
103102
void set_error(_Error&& __error) noexcept {
104103
// store error and signal stop
@@ -110,8 +109,7 @@ namespace exec {
110109
requires __variant_emplaceable<
111110
_ResultVariant,
112111
__decayed_std_tuple<set_stopped_t>,
113-
set_stopped_t
114-
>
112+
set_stopped_t>
115113
&& __callable<set_stopped_t, _ItemReceiver>
116114
{
117115
// stop without error
@@ -190,11 +188,11 @@ namespace exec {
190188
using receiver_concept = stdexec::receiver_t;
191189
__operation_base<_Receiver, _ResultVariant>* __op_;
192190

193-
template <same_as<__t> _Self, sender _Item>
194-
STDEXEC_MEMFN_DECL(auto set_next)(this _Self& __self, _Item&& __item)
195-
noexcept(__nothrow_decay_copyable<_Item>)
196-
-> stdexec::__t<__item_sender<__decay_t<_Item>, _ResultVariant>> {
197-
return {static_cast<_Item&&>(__item), __self.__op_};
191+
template <sender _Item>
192+
[[nodiscard]]
193+
auto set_next(_Item&& __item) & noexcept(__nothrow_decay_copyable<_Item>)
194+
-> stdexec::__t<__item_sender<__decay_t<_Item>, _ResultVariant>> {
195+
return {static_cast<_Item&&>(__item), __op_};
198196
}
199197

200198
void set_value() noexcept {
@@ -227,8 +225,7 @@ namespace exec {
227225
__mconst<__types<>>::__f,
228226
__mcompose_q<__types, __mbind_front_q<__decayed_std_tuple, set_error_t>::__f>::__f,
229227
__types<std::tuple<set_stopped_t>>,
230-
__mconcat<__qq<__nullable_std_variant>>::__f
231-
>;
228+
__mconcat<__qq<__nullable_std_variant>>::__f>;
232229

233230
template <class _Sender, class _Env>
234231
using __result_variant_t =
@@ -324,8 +321,7 @@ namespace exec {
324321
requires receiver_of<_Receiver, __completion_sigs<__child_of<_Sender>, env_of_t<_Receiver>>>
325322
&& sequence_sender_to<
326323
__child_of<_Sender>,
327-
__receiver_t<__child_of<_Sender>, _Receiver>
328-
>
324+
__receiver_t<__child_of<_Sender>, _Receiver>>
329325
{
330326
static_assert(sender_expr_for<_Sender, ignore_all_values_t>);
331327
return __sexpr_apply(static_cast<_Sender&&>(__sndr), __connect_fn<_Receiver>{__rcvr});

include/exec/sequence/iterate.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
# include "../sequence_senders.hpp"
2626
# include "../__detail/__basic_sequence.hpp"
2727

28-
# include "../env.hpp"
2928
# include "../trampoline_scheduler.hpp"
3029

3130
# include <exception>
@@ -186,8 +185,7 @@ namespace exec {
186185

187186
template <
188187
sender_expr_for<iterate_t> _SeqExpr,
189-
sequence_receiver_of<item_types<_ItemSender<_SeqExpr>>> _Receiver
190-
>
188+
sequence_receiver_of<item_types<_ItemSender<_SeqExpr>>> _Receiver>
191189
requires sender_to<_NextSender<_SeqExpr, _Receiver>, _NextReceiver<_SeqExpr, _Receiver>>
192190
static auto subscribe(_SeqExpr&& __seq, _Receiver __rcvr)
193191
noexcept(__nothrow_callable<__sexpr_apply_t, _SeqExpr, __subscribe_fn<_Receiver>>)
@@ -201,8 +199,8 @@ namespace exec {
201199
}
202200

203201
template <sender_expr_for<iterate_t> _Sequence>
204-
static auto
205-
get_item_types(_Sequence&&, __ignore) noexcept -> item_types<_ItemSender<_Sequence>> {
202+
static auto get_item_types(_Sequence&&, __ignore) noexcept //
203+
-> item_types<_ItemSender<_Sequence>> {
206204
return {};
207205
}
208206

0 commit comments

Comments
 (0)