1+ /*
2+ * Copyright (c) 2023 Maikel Nadolski
3+ * Copyright (c) 2023 NVIDIA Corporation
4+ *
5+ * Licensed under the Apache License Version 2.0 with LLVM Exceptions
6+ * (the "License"); you may not use this file except in compliance with
7+ * the License. You may obtain a copy of the License at
8+ *
9+ * https://llvm.org/LICENSE.txt
10+ *
11+ * Unless required by applicable law or agreed to in writing, software
12+ * distributed under the License is distributed on an "AS IS" BASIS,
13+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+ * See the License for the specific language governing permissions and
15+ * limitations under the License.
16+ */
17+ #pragma once
18+
19+ #include " ../sequence_senders.hpp"
20+
21+ #include " ../__detail/__basic_sequence.hpp"
22+
23+ namespace exec {
24+ namespace __transform_each {
25+ using namespace stdexec ;
26+
27+ template <class _Receiver , class _Adaptor >
28+ struct __operation_base {
29+ _Receiver __receiver_;
30+ _Adaptor __adaptor_;
31+ };
32+
33+ template <class _ReceiverId , class _Adaptor >
34+ struct __receiver {
35+ using _Receiver = stdexec::__t <_ReceiverId>;
36+
37+ struct __t {
38+ using is_receiver = void ;
39+ using __id = __receiver;
40+ __operation_base<_Receiver, _Adaptor>* __op_;
41+
42+ template <same_as<set_next_t > _SetNext, same_as<__t > _Self, class _Item >
43+ requires __callable<_Adaptor&, _Item>
44+ && __callable<exec::set_next_t , _Receiver&, __call_result_t <_Adaptor&, _Item>>
45+ friend auto tag_invoke (_SetNext, _Self& __self, _Item&& __item) noexcept (
46+ __nothrow_callable<_SetNext, _Receiver&, __call_result_t <_Adaptor&, _Item>> //
47+ && __nothrow_callable<_Adaptor&, _Item>)
48+ -> next_sender_of_t<_Receiver, __call_result_t<_Adaptor&, _Item>> {
49+ return exec::set_next (
50+ __self.__op_ ->__receiver_ , __self.__op_ ->__adaptor_ (static_cast <_Item&&>(__item)));
51+ }
52+
53+ template <same_as<set_value_t > _SetValue, same_as<__t > _Self>
54+ friend void tag_invoke (_SetValue, _Self&& __self) noexcept {
55+ stdexec::set_value (static_cast <_Receiver&&>(__self.__op_ ->__receiver_ ));
56+ }
57+
58+ template <same_as<set_stopped_t > _SetStopped, same_as<__t > _Self>
59+ requires __callable<_SetStopped, _Receiver&&>
60+ friend void tag_invoke (_SetStopped, _Self&& __self) noexcept {
61+ stdexec::set_stopped (static_cast <_Receiver&&>(__self.__op_ ->__receiver_ ));
62+ }
63+
64+ template <same_as<set_error_t > _SetError, same_as<__t > _Self, class _Error >
65+ requires __callable<_SetError, _Receiver&&, _Error>
66+ friend void tag_invoke (_SetError, _Self&& __self, _Error&& __error) noexcept {
67+ stdexec::set_error (
68+ static_cast <_Receiver&&>(__self.__op_ ->__receiver_ ), static_cast <_Error&&>(__error));
69+ }
70+
71+ template <same_as<get_env_t > _GetEnv, __decays_to<__t > _Self>
72+ friend env_of_t <_Receiver> tag_invoke (_GetEnv, _Self&& __self) noexcept {
73+ return stdexec::get_env (__self.__op_ ->__receiver_ );
74+ }
75+ };
76+ };
77+
78+ template <class _Sender , class _ReceiverId , class _Adaptor >
79+ struct __operation {
80+ using _Receiver = stdexec::__t <_ReceiverId>;
81+
82+ struct __t : __operation_base<_Receiver, _Adaptor> {
83+ using __id = __operation;
84+ subscribe_result_t <_Sender, stdexec::__t <__receiver<_ReceiverId, _Adaptor>>> __op_;
85+
86+ __t (_Sender&& __sndr, _Receiver __rcvr, _Adaptor __adaptor)
87+ : __operation_base<
88+ _Receiver,
89+ _Adaptor>{static_cast <_Receiver&&>(__rcvr), static_cast <_Adaptor&&>(__adaptor)}
90+ , __op_{exec::subscribe (
91+ static_cast <_Sender&&>(__sndr),
92+ stdexec::__t <__receiver<_ReceiverId, _Adaptor>>{this })} {
93+ }
94+
95+ friend void tag_invoke (start_t , __t & __self) noexcept {
96+ stdexec::start (__self.__op_ );
97+ }
98+ };
99+ };
100+
101+ template <class _Receiver >
102+ struct __subscribe_fn {
103+ _Receiver& __rcvr_;
104+
105+ template <class _Adaptor , class _Sequence >
106+ auto operator ()(__ignore, _Adaptor __adaptor, _Sequence&& __sequence) noexcept (
107+ __nothrow_decay_copyable<_Adaptor> && __nothrow_decay_copyable<_Sequence>
108+ && __nothrow_decay_copyable<_Receiver>)
109+ -> __t< __operation<_Sequence, __id<_Receiver>, _Adaptor>> {
110+ return {
111+ static_cast <_Sequence&&>(__sequence),
112+ static_cast <_Receiver&&>(__rcvr_),
113+ static_cast <_Adaptor&&>(__adaptor)};
114+ }
115+ };
116+
117+ template <class _Adaptor >
118+ struct _NOT_CALLABLE_ADAPTOR_ { };
119+
120+ template <class _Item >
121+ struct _WITH_ITEM_SENDER_ { };
122+
123+ template <class _Adaptor , class _Item >
124+ auto __try_call (_Item*)
125+ -> stdexec::__mexception<_NOT_CALLABLE_ADAPTOR_<_Adaptor&>, _WITH_ITEM_SENDER_<stdexec::__name_of<_Item>>>;
126+
127+ template <class _Adaptor , class _Item >
128+ requires stdexec::__callable<_Adaptor&, _Item>
129+ stdexec::__msuccess __try_call (_Item*);
130+
131+ template <class _Adaptor , class ... _Items>
132+ auto __try_calls (item_types<_Items...>*)
133+ -> decltype((stdexec::__msuccess() && ... && __try_call<_Adaptor>((_Items*) nullptr)));
134+
135+ template <class _Adaptor , class _Items >
136+ concept __callabale_adaptor_for = requires (_Items* __items) {
137+ { __try_calls<stdexec::__decay_t <_Adaptor>>(__items) } -> stdexec::__ok;
138+ };
139+
140+ struct transform_each_t {
141+ template <sender _Sequence, __sender_adaptor_closure _Adaptor>
142+ auto operator ()(_Sequence&& __sndr, _Adaptor&& __adaptor) const noexcept (
143+ __nothrow_decay_copyable<_Sequence> //
144+ && __nothrow_decay_copyable<_Adaptor>) {
145+ return make_sequence_expr<transform_each_t >(
146+ static_cast <_Adaptor&&>(__adaptor), static_cast <_Sequence&&>(__sndr));
147+ }
148+
149+ template <class _Adaptor >
150+ constexpr auto operator ()(_Adaptor __adaptor) const noexcept
151+ -> __binder_back<transform_each_t, _Adaptor> {
152+ return {{}, {}, {static_cast <_Adaptor&&>(__adaptor)}};
153+ }
154+
155+ template <class _Self , class _Env >
156+ using __completion_sigs_t = __sequence_completion_signatures_of_t <__child_of<_Self>, _Env>;
157+
158+ template <sender_expr_for<transform_each_t > _Self, class _Env >
159+ static __completion_sigs_t <_Self, _Env> get_completion_signatures (_Self&&, _Env&&) noexcept {
160+ return {};
161+ }
162+
163+ template <class _Self , class _Env >
164+ using __item_types_t = stdexec::__mapply<
165+ stdexec::__transform<
166+ stdexec::__mbind_front_q<__call_result_t , __data_of<_Self>&>,
167+ stdexec::__munique<stdexec::__q<item_types>>>,
168+ item_types_of_t <__child_of<_Self>, _Env>>;
169+
170+ template <sender_expr_for<transform_each_t > _Self, class _Env >
171+ static __item_types_t <_Self, _Env> get_item_types (_Self&&, _Env&&) noexcept {
172+ return {};
173+ }
174+
175+ template <class _Self , class _Receiver >
176+ using __receiver_t = __t <__receiver<__id<_Receiver>, __data_of<_Self>>>;
177+
178+ template <class _Self , class _Receiver >
179+ using __operation_t = __t < __operation<__child_of<_Self>, __id<_Receiver>, __data_of<_Self>>>;
180+
181+ template <sender_expr_for<transform_each_t > _Self, receiver _Receiver>
182+ requires __callabale_adaptor_for<
183+ __data_of<_Self>,
184+ __item_types_t <_Self, env_of_t <_Receiver>>>
185+ && sequence_receiver_of<_Receiver, __item_types_t <_Self, env_of_t <_Receiver>>>
186+ && sequence_sender_to<__child_of<_Self>, __receiver_t <_Self, _Receiver>>
187+ static auto subscribe (_Self&& __self, _Receiver __rcvr) noexcept (
188+ __nothrow_callable<apply_sender_t , _Self, __subscribe_fn<_Receiver>>)
189+ -> __call_result_t<apply_sender_t, _Self, __subscribe_fn<_Receiver>> {
190+ return apply_sender (static_cast <_Self&&>(__self), __subscribe_fn<_Receiver>{__rcvr});
191+ }
192+
193+ template <sender_expr_for<transform_each_t > _Sexpr>
194+ static env_of_t <__child_of<_Sexpr>> get_env (const _Sexpr& __sexpr) noexcept {
195+ return apply_sender (__sexpr, []<class _Child >(__ignore, __ignore, const _Child& __child) {
196+ return stdexec::get_env (__child);
197+ });
198+ }
199+ };
200+ }
201+
202+ using __transform_each::transform_each_t ;
203+ inline constexpr transform_each_t transform_each{};
204+ }
0 commit comments