@@ -35,8 +35,8 @@ namespace exec {
3535 using namespace STDEXEC ;
3636
3737 template <class _Receiver >
38- struct __repeat_n_state_base {
39- constexpr explicit __repeat_n_state_base (_Receiver &&__rcvr, std::size_t __count) noexcept
38+ struct __opstate_base : __immovable {
39+ constexpr explicit __opstate_base (_Receiver &&__rcvr, std::size_t __count) noexcept
4040 : __rcvr_{static_cast <_Receiver &&>(__rcvr)}
4141 , __count_{__count} {
4242 }
@@ -49,9 +49,8 @@ namespace exec {
4949 trampoline_scheduler __sched_;
5050 };
5151
52- template <class _SenderId , class _ReceiverId >
52+ template <class _ReceiverId >
5353 struct __receiver {
54- using _Sender = STDEXEC::__t <_SenderId>;
5554 using _Receiver = STDEXEC::__t <_ReceiverId>;
5655
5756 struct __t {
@@ -86,54 +85,43 @@ namespace exec {
8685 return STDEXEC::get_env (__state_->__rcvr_ );
8786 }
8887
89- __repeat_n_state_base <_Receiver> *__state_;
88+ __opstate_base <_Receiver> *__state_;
9089 };
9190 };
9291
93- template <class _Child >
94- struct __child_count_pair {
95- _Child __child_;
96- std::size_t __count_;
97- };
98-
99- template <class _Child >
100- STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
101- __child_count_pair (_Child, std::size_t ) -> __child_count_pair<_Child>;
102-
103- template <class _Sender , class _Receiver >
104- struct __repeat_n_state : __repeat_n_state_base<_Receiver> {
105- using __child_count_pair_t = __decay_t <__data_of<_Sender>>;
106- using __child_t = decltype (__child_count_pair_t ::__child_);
107- using __receiver_t = STDEXEC::__t <__receiver<__id<_Sender>, __id<_Receiver>>>;
108- using __child_on_sched_sender_t =
109- __result_of<exec::sequence, schedule_result_t <trampoline_scheduler>, __child_t &>;
110- using __child_op_t = STDEXEC::connect_result_t <__child_on_sched_sender_t , __receiver_t >;
111-
112- constexpr explicit __repeat_n_state (_Sender &&__sndr, _Receiver &&__rcvr)
113- : __repeat_n_state_base<_Receiver>{
114- static_cast <_Receiver &&>(__rcvr),
115- STDEXEC::__get<1 >(static_cast <_Sender &&>(__sndr)).__count_ }
116- , __child_(STDEXEC::__get<1 >(static_cast <_Sender &&>(__sndr)).__child_) {
92+ template <class _Child , class _Receiver >
93+ struct __opstate : __opstate_base<_Receiver> {
94+ using __receiver_t = STDEXEC::__t <__receiver<__id<_Receiver>>>;
95+ using __bouncy_sndr_t =
96+ __result_of<exec::sequence, schedule_result_t <trampoline_scheduler>, _Child &>;
97+ using __child_op_t = STDEXEC::connect_result_t <__bouncy_sndr_t , __receiver_t >;
98+ static constexpr bool __nothrow_connect =
99+ STDEXEC::__nothrow_connectable<__bouncy_sndr_t , __receiver_t >;
100+
101+ constexpr explicit __opstate (std::size_t __count, _Child __child, _Receiver __rcvr)
102+ noexcept (__nothrow_connect)
103+ : __opstate_base<_Receiver>{static_cast <_Receiver &&>(__rcvr), __count}
104+ , __child_(std::move(__child)) {
117105 if (this ->__count_ != 0 ) {
118106 __connect ();
119107 }
120108 }
121109
122- constexpr auto __connect () -> __child_op_t & {
123- return __child_op_.__emplace_from (
124- STDEXEC::connect,
125- exec::sequence (STDEXEC::schedule (this ->__sched_ ), __child_),
126- __receiver_t {this });
127- }
128-
129- constexpr void __start () noexcept {
110+ constexpr void start () noexcept {
130111 if (this ->__count_ == 0 ) {
131112 STDEXEC::set_value (static_cast <_Receiver &&>(this ->__rcvr_ ));
132113 } else {
133114 STDEXEC::start (*__child_op_);
134115 }
135116 }
136117
118+ constexpr auto __connect () noexcept (__nothrow_connect) -> __child_op_t & {
119+ return __child_op_.__emplace_from (
120+ STDEXEC::connect,
121+ exec::sequence (STDEXEC::schedule (this ->__sched_ ), __child_),
122+ __receiver_t {this });
123+ }
124+
137125 constexpr void __cleanup () noexcept final {
138126 __child_op_.reset ();
139127 }
@@ -153,18 +141,14 @@ namespace exec {
153141 }
154142 }
155143
156- __child_t __child_;
144+ _Child __child_;
157145 STDEXEC::__optional<__child_op_t > __child_op_;
158146 };
159147
160- template <class _Sender , class _Receiver >
161- STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
162- __repeat_n_state (_Sender &&, _Receiver) -> __repeat_n_state<_Sender, _Receiver>;
163-
164148 struct repeat_n_t ;
165149 struct _REPEAT_N_EXPECTS_A_SENDER_OF_VOID_ ;
166150
167- template <class _Sender , class ... _Args>
151+ template <class _Child , class ... _Args>
168152 using __values_t =
169153 // There's something funny going on with __if_c here. Use std::conditional_t instead. :-(
170154 std::conditional_t <
@@ -173,43 +157,41 @@ namespace exec {
173157 __mexception<
174158 _REPEAT_N_EXPECTS_A_SENDER_OF_VOID_,
175159 _WHERE_ (_IN_ALGORITHM_, repeat_n_t ),
176- _WITH_PRETTY_SENDER_<_Sender >
160+ _WITH_PRETTY_SENDER_<_Child >
177161 >
178162 >;
179163
180164 template <class _Error >
181165 using __error_t = completion_signatures<set_error_t (__decay_t <_Error>)>;
182166
183- template <class _Pair , class ... _Env>
167+ template <class _Child , class ... _Env>
184168 using __completions_t = STDEXEC::transform_completion_signatures<
185- __completion_signatures_of_t <decltype ( __decay_t <_Pair>::__child_) &, _Env...>,
169+ __completion_signatures_of_t <_Child &, _Env...>,
186170 STDEXEC::transform_completion_signatures<
187171 __completion_signatures_of_t <STDEXEC::schedule_result_t <exec::trampoline_scheduler>, _Env...>,
188172 __eptr_completion,
189173 __cmplsigs::__default_set_value,
190174 __error_t
191175 >,
192- __mbind_front_q<__values_t , decltype ( __decay_t <_Pair>::__child_) >::template __f,
176+ __mbind_front_q<__values_t , _Child >::template __f,
193177 __error_t
194178 >;
195179
196- struct __repeat_n_tag { };
197-
198- struct __repeat_n_impl : __sexpr_defaults {
180+ struct __impls : __sexpr_defaults {
199181 template <class _Sender , class ... _Env>
200182 static consteval auto get_completion_signatures () {
201183 // TODO: port this to use constant evaluation
202- return __completions_t <__data_of <_Sender>, _Env...>{};
184+ return __completions_t <__child_of <_Sender>, _Env...>{};
203185 }
204186
205- static constexpr auto get_state = []< class _Sender , class _Receiver >(
206- _Sender &&__sndr,
207- _Receiver &&__rcvr ) {
208- return __repeat_n_state{ static_cast <_Sender &&>(__sndr), static_cast <_Receiver &&>(__rcvr)} ;
209- };
210-
211- static constexpr auto start = []( auto &__state) noexcept -> void {
212- __state. __start ( );
187+ static constexpr auto connect = //
188+ []< class _Receiver , class _Sender >(_Sender &&__sndr, _Receiver &&__rcvr) noexcept (
189+ noexcept (__opstate( 0 , STDEXEC::__get< 2 >(__declval<_Sender>()), __declval< _Receiver>())) ) {
190+ const std:: size_t __count = STDEXEC::__get< 1 >(__sndr) ;
191+ return __opstate (
192+ __count,
193+ STDEXEC::__get< 2 >( static_cast <_Sender &&>(__sndr)),
194+ static_cast <_Receiver &&>(__rcvr) );
213195 };
214196 };
215197
@@ -223,14 +205,6 @@ namespace exec {
223205 constexpr auto operator ()(std::size_t __count) const noexcept {
224206 return __closure (*this , __count);
225207 }
226-
227- template <class _Sender >
228- static auto transform_sender (set_value_t , _Sender &&__sndr, __ignore)
229- noexcept (__nothrow_decay_copyable<_Sender>) {
230- auto &[__tag, __count, __child] = __sndr;
231- return __make_sexpr<__repeat_n_tag>(
232- __child_count_pair{STDEXEC::__forward_like<_Sender>(__child), __count});
233- }
234208 };
235209 } // namespace __repeat_n
236210
@@ -240,17 +214,7 @@ namespace exec {
240214
241215namespace STDEXEC {
242216 template <>
243- struct __sexpr_impl <exec::__repeat_n::__repeat_n_tag> : exec::__repeat_n::__repeat_n_impl { };
244-
245- template <>
246- struct __sexpr_impl <exec::repeat_n_t > : __sexpr_defaults {
247- template <class _Sender , class ... _Env>
248- static consteval auto get_completion_signatures () {
249- using __sndr_t =
250- __detail::__transform_sender_result_t <exec::repeat_n_t , set_value_t , _Sender, env<>>;
251- return STDEXEC::get_completion_signatures<__sndr_t , _Env...>();
252- };
253- };
217+ struct __sexpr_impl <exec::repeat_n_t > : exec::__repeat_n::__impls { };
254218} // namespace STDEXEC
255219
256220STDEXEC_PRAGMA_POP ()
0 commit comments