1 /*
2  * Copyright (c) 2021-2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "__concepts.hpp"
19 #include "__config.hpp"
20 #include "__type_traits.hpp"
21 #include "__utility.hpp"
22 
23 #include <cassert>
24 #include <compare>
25 #include <cstddef>
26 #include <exception>
27 #include <type_traits>
28 #include <utility>
29 
30 namespace stdexec
31 {
32 template <class _Tp>
33 using __t = typename _Tp::__t;
34 
35 template <class _Ty>
36 struct __mtype
37 {
38     using __t = _Ty;
39 };
40 
41 template <class...>
42 inline constexpr bool __mnever = false;
43 
44 template <auto _Value>
45 using __mtypeof = decltype(_Value);
46 
47 template <class...>
48 struct __types;
49 
50 template <class _Tp>
51 using __midentity = _Tp;
52 
53 template <auto _Np>
54 struct __mconstant
55 {
56     using type = __mconstant;
57     using value_type = __mtypeof<_Np>;
58     static constexpr auto value = _Np;
59 
operator value_typestdexec::__mconstant60     constexpr operator value_type() const noexcept
61     {
62         return value;
63     }
64 
operator ()stdexec::__mconstant65     constexpr auto operator()() const noexcept -> value_type
66     {
67         return value;
68     }
69 };
70 
71 // Because of nvc++ nvbugs#4679848, we can't make __mbool a simple alias for
72 // __mconstant, and because of nvc++ nvbugs#4668709 it can't be a simple alias
73 // for std::bool_constant, either. :-( template <bool _Bp> using __mbool =
74 // __mconstant<_Bp>;
75 
76 template <bool _Bp>
77 struct __mbool : std::bool_constant<_Bp>
78 {};
79 
80 using __mtrue = __mbool<true>;
81 using __mfalse = __mbool<false>;
82 
83 // nvbugs#4679848 and nvbugs#4668709 also preclude __mconstant from representing
84 // a compile-time size_t.
85 enum class __muchar : unsigned char
86 {
87 };
88 
89 #if STDEXEC_MSVC()
90 template <std::size_t _Np>
91 using __msize_t = __mconstant<_Np>;
92 #else
93 template <std::size_t _Np>
94 using __msize_t = __muchar (*)[_Np + 1]; // +1 to avoid zero-size array
95 #endif
96 
97 template <class _Tp, class _Up>
98 using __mfirst = _Tp;
99 
100 template <class _Tp, class _Up>
101 using __msecond = _Up;
102 
103 template <class...>
104 struct __undefined;
105 
106 template <class _Tp>
107 extern const __undefined<_Tp> __v;
108 
109 template <class _Tp>
110     requires __typename<__mtypeof<_Tp::value>>
111 inline constexpr auto __v<_Tp> = _Tp::value;
112 
113 // These specializations exist because instantiating a variable template is
114 // cheaper than instantiating a class template.
115 template <class _Tp, class _Up>
116 inline constexpr bool __v<std::is_same<_Tp, _Up>> = false;
117 
118 template <class _Tp>
119 inline constexpr bool __v<std::is_same<_Tp, _Tp>> = true;
120 
121 template <class _Tp, _Tp _Ip>
122 inline constexpr _Tp __v<std::integral_constant<_Tp, _Ip>> = _Ip;
123 
124 template <auto _Np>
125 inline constexpr auto __v<__mconstant<_Np>> = _Np;
126 
127 template <std::size_t _Np>
128 inline constexpr std::size_t __v<__muchar (*)[_Np]> =
129     _Np - 1; // see definition of __msize_t
130 
131 namespace __pack
132 {
133 template <std::size_t... _Is>
134 struct __t;
135 } // namespace __pack
136 
137 template <std::size_t... _Is>
138 using __indices = __pack::__t<_Is...>*;
139 
140 #if STDEXEC_MSVC()
141 namespace __pack
142 {
143 template <class _Ty, _Ty... _Is>
144 struct __idx;
145 
146 template <class>
147 extern int __mkidx;
148 
149 template <std::size_t... _Is>
150 extern __indices<_Is...> __mkidx<__idx<std::size_t, _Is...>>;
151 } // namespace __pack
152 
153 template <std::size_t _Np>
154 using __make_indices = //
155     decltype(__pack::__mkidx<
156              __make_integer_seq<__pack::__idx, std::size_t, _Np>>);
157 #elif STDEXEC_HAS_BUILTIN(__make_integer_seq)
158 namespace __pack
159 {
160 template <class _Ty, _Ty... _Is>
161 using __idx = __indices<_Is...>;
162 } // namespace __pack
163 
164 template <std::size_t _Np>
165 using __make_indices = __make_integer_seq<__pack::__idx, std::size_t, _Np>;
166 #elif STDEXEC_HAS_BUILTIN(__integer_pack)
167 namespace __pack
168 {
169 template <std::size_t _Np>
170 extern __indices<__integer_pack(_Np)...> __make_indices;
171 } // namespace __pack
172 
173 template <std::size_t _Np>
174 using __make_indices = decltype(__pack::__make_indices<_Np>);
175 #else
176 namespace __pack
177 {
178 template <std::size_t... _Is>
179 auto __mk_indices(__indices<0, _Is...>) -> __indices<_Is...>;
180 
181 template <std::size_t _Np, class = char[_Np], std::size_t... _Is>
182 auto __mk_indices(__indices<_Np, _Is...>)
183     -> decltype(__mk_indices(__indices<_Np - 1, 0, (_Is + 1)...>{}));
184 } // namespace __pack
185 
186 template <std::size_t _Np>
187 using __make_indices = decltype(__pack::__mk_indices(__indices<_Np>{}));
188 #endif
189 
190 template <class... _Ts>
191 using __indices_for = __make_indices<sizeof...(_Ts)>;
192 
193 STDEXEC_PRAGMA_PUSH()
194 STDEXEC_PRAGMA_IGNORE_MSVC(4293)
195 
__mpow2(std::size_t __size)196 constexpr std::size_t __mpow2(std::size_t __size) noexcept
197 {
198     --__size;
199     __size |= __size >> 1;
200     __size |= __size >> 2;
201     __size |= __size >> 4;
202     __size |= __size >> 8;
203     if constexpr (sizeof(__size) >= 4)
204         __size |= __size >> 16;
205     if constexpr (sizeof(__size) >= 8)
206         __size |= __size >> 32;
207     return ++__size;
208 }
209 
210 STDEXEC_PRAGMA_POP()
211 
212 template <std::size_t _Len>
213 struct __mstring
214 {
215 #if STDEXEC_NVHPC()
216     template <std::size_t _Ny, std::size_t... _Is>
__mstringstdexec::__mstring217     constexpr __mstring(const char (&__str)[_Ny], __indices<_Is...>) noexcept :
218         __what_{(_Is < _Ny ? __str[_Is] : '\0')...}
219     {}
220 
221     template <std::size_t _Ny>
__mstringstdexec::__mstring222     constexpr __mstring(const char (&__str)[_Ny], int = 0) noexcept :
223         __mstring{__str, __make_indices<_Len>{}}
224     {}
225 #else
226     template <std::size_t _Ny>
227     constexpr __mstring(const char (&__str)[_Ny], int = 0) noexcept : __what_{}
228     {
229         for (auto __i = 0ull; char __ch : __str)
230         {
231             __what_[__i++] = __ch;
232         }
233     }
234 #endif
235 
__lengthstdexec::__mstring236     static constexpr auto __length() noexcept -> std::size_t
237     {
238         return _Len;
239     }
240 
241     constexpr auto
242         operator==(const __mstring&) const noexcept -> bool = default;
243 
244     template <std::size_t _OtherLen>
245     constexpr auto
operator ==stdexec::__mstring246         operator==(const __mstring<_OtherLen>&) const noexcept -> bool
247     {
248         return false;
249     }
250 
251 #if !STDEXEC_NVHPC()
252     constexpr auto operator<=>(const __mstring&) const noexcept
253         -> std::strong_ordering = default;
254 #endif
255 
256     template <std::size_t _OtherLen>
operator <=>stdexec::__mstring257     constexpr auto operator<=>(const __mstring<_OtherLen>& __other)
258         const noexcept -> std::strong_ordering
259     {
260         constexpr std::size_t __len = _Len < _OtherLen ? _Len : _OtherLen;
261         for (std::size_t __i = 0; __i < __len; ++__i)
262         {
263             auto __cmp = (__what_[__i] <=> __other.__what_[__i]);
264             if (__cmp != 0)
265             {
266                 return __cmp;
267             }
268         }
269         if constexpr (_Len == _OtherLen)
270         {
271             return std::strong_ordering::equal;
272         }
273         return (_Len < _OtherLen) ? std::strong_ordering::less
274                                   : std::strong_ordering::greater;
275     }
276 
277     char __what_[_Len];
278 };
279 
280 template <std::size_t _Len>
281 __mstring(const char (&__str)[_Len]) -> __mstring<_Len>;
282 
283 template <std::size_t _Len>
284 __mstring(const char (&__str)[_Len], int) -> __mstring<__mpow2(_Len)>;
285 
286 STDEXEC_PRAGMA_PUSH()
287 STDEXEC_PRAGMA_IGNORE_GNU("-Wuser-defined-literals")
288 
289 // Use a standard user-defined string literal template
290 template <__mstring _Str>
291 [[deprecated("Use _mstr instead")]] constexpr auto
operator ""__csz()292     operator""__csz() noexcept -> __mtypeof<_Str>
293 {
294     return _Str;
295 }
296 
297 // Use a standard user-defined string literal template
298 template <__mstring _Str>
operator ""_mstr()299 constexpr auto operator""_mstr() noexcept -> __mtypeof<_Str>
300 {
301     return _Str;
302 }
303 
STDEXEC_PRAGMA_POP()304 STDEXEC_PRAGMA_POP()
305 
306 template <class T>
307 constexpr auto __mnameof() noexcept
308 {
309 #if STDEXEC_MSVC()
310     return __mstring{__FUNCSIG__, 0};
311 #else
312     return __mstring{__PRETTY_FUNCTION__, 0};
313 #endif
314 }
315 
316 using __msuccess = int;
317 
318 template <class _What, class... _With>
319 struct _WARNING_
320 {};
321 
322 template <class _What, class... _With>
323 struct _ERROR_
324 {
325     auto operator,(__msuccess) const noexcept -> _ERROR_;
326 };
327 
328 template <__mstring... _What>
329 struct _WHAT_
330 {};
331 
332 template <class _What, class... _With>
333 using __mexception = _ERROR_<_What, _With...>;
334 
335 template <class>
336 extern __msuccess __ok_v;
337 
338 template <class _What, class... _With>
339 extern _ERROR_<_What, _With...> __ok_v<__mexception<_What, _With...>>;
340 
341 template <class _Ty>
342 using __ok_t = decltype(__ok_v<_Ty>);
343 
344 template <class... _Ts>
345 using __disp = decltype((__msuccess(), ..., __ok_t<_Ts>()));
346 
347 template <class _Arg>
348 concept __ok = STDEXEC_IS_SAME(__ok_t<_Arg>, __msuccess);
349 
350 template <class _Arg>
351 concept __merror = !STDEXEC_IS_SAME(__ok_t<_Arg>, __msuccess);
352 
353 template <class... _Args>
354 concept _Ok = (STDEXEC_IS_SAME(__ok_t<_Args>, __msuccess) && ...);
355 
356 template <bool _ArgsOK, bool _FnOK = true>
357 struct __i;
358 
359 #if STDEXEC_NVHPC()
360 // Most compilers memoize alias template specializations, but
361 // nvc++ does not. So we memoize the type computations by
362 // indirecting through a class template specialization.
363 template <template <class...> class _Fn, class... _Args>
364 using __meval__ =                  //
365     typename __i<_Ok<_Args...>>    //
366     ::template __g<_Fn, _Args...>; //
367 
368 template <template <class...> class _Fn, class... _Args>
369 struct __meval_
370 {};
371 
372 template <template <class...> class _Fn, class... _Args>
373     requires __typename<__meval__<_Fn, _Args...>>
374 struct __meval_<_Fn, _Args...>
375 {
376     using __t = __meval__<_Fn, _Args...>;
377 };
378 
379 template <template <class...> class _Fn, class... _Args>
380 using __meval = __t<__meval_<_Fn, _Args...>>;
381 
382 template <class _Fn, class... _Args>
383 using __minvoke__ =                       //
384     typename __i<_Ok<_Args...>, _Ok<_Fn>> //
385     ::template __f<_Fn>                   //
386     ::template __f<_Args...>;             //
387 
388 template <class _Fn, class... _Args>
389 struct __minvoke_
390 {};
391 
392 template <class _Fn, class... _Args>
393     requires __typename<__minvoke__<_Fn, _Args...>>
394 struct __minvoke_<_Fn, _Args...>
395 {
396     using __t = __minvoke__<_Fn, _Args...>;
397 };
398 
399 template <class _Fn, class... _Args>
400 using __minvoke = __t<__minvoke_<_Fn, _Args...>>;
401 
402 #else
403 
404 template <template <class...> class _Fn, class... _Args>
405 using __meval =                    //
406     typename __i<_Ok<_Args...>>    //
407     ::template __g<_Fn, _Args...>; //
408 
409 template <class _Fn, class... _Args>
410 using __minvoke =                         //
411     typename __i<_Ok<_Args...>, _Ok<_Fn>> //
412     ::template __f<_Fn>                   //
413     ::template __f<_Args...>;             //
414 
415 #endif
416 
417 template <class _Fn, class... _Args>
418 using __mcall = typename _Fn::template __f<_Args...>;
419 
420 struct __disp_q
421 {
422     template <class... _Args>
423     using __f = __disp<_Args...>;
424 };
425 
426 template <>
427 struct __i<true, true>
428 {
429     template <template <class...> class _Fn, class... _Args>
430     using __g = _Fn<_Args...>;
431 
432     template <class _Fn>
433     using __f = _Fn;
434 };
435 
436 template <>
437 struct __i<false, true>
438 {
439     template <template <class...> class, class... _Args>
440     using __g = __disp<_Args...>;
441 
442     template <class>
443     using __f = __disp_q;
444 };
445 
446 template <bool _ArgsOK>
447 struct __i<_ArgsOK, false>
448 {
449     template <class _Fn>
450     using __f = _Fn;
451 };
452 
453 template <template <class...> class _Fn>
454 struct __q
455 {
456     template <class... _Args>
457     using __f = typename __i<_Ok<_Args...>>::template __g<_Fn, _Args...>;
458 };
459 
460 template <template <class...> class _Fn>
461 struct __qq
462 {
463     template <class... _Args>
464     using __f = _Fn<_Args...>;
465 };
466 
467 template <template <class> class _Fn>
468 struct __q1
469 {
470     template <class _Ty>
471     using __f = _Fn<_Ty>;
472 };
473 
474 template <template <class, class> class _Fn>
475 struct __q2
476 {
477     template <class _Ty, class _Uy>
478     using __f = _Fn<_Ty, _Uy>;
479 };
480 
481 template <template <class...> class _Fn>
482 using __mtry_q = __q<_Fn>;
483 
484 template <class _Fn>
485 struct __mtry : __mtry_q<_Fn::template __f>
486 {};
487 
488 template <template <class...> class _Fn, class... _Front>
489 struct __mbind_front_q
490 {
491     template <class... _Args>
492     using __f = __meval<_Fn, _Front..., _Args...>;
493 };
494 
495 template <class _Fn, class... _Front>
496 using __mbind_front = __mbind_front_q<_Fn::template __f, _Front...>;
497 
498 template <template <class...> class _Fn, class... _Back>
499 struct __mbind_back_q
500 {
501     template <class... _Args>
502     using __f = __meval<_Fn, _Args..., _Back...>;
503 };
504 
505 template <class _Fn, class... _Back>
506 using __mbind_back = __mbind_back_q<_Fn::template __f, _Back...>;
507 
508 template <template <class...> class _Tp, class... _Args>
509 concept __mvalid = requires { typename __meval<_Tp, _Args...>; };
510 
511 template <class _Fn, class... _Args>
512 concept __minvocable = __mvalid<_Fn::template __f, _Args...>;
513 
514 template <template <class...> class _Tp, class... _Args>
515 concept __msucceeds = __mvalid<_Tp, _Args...> && __ok<__meval<_Tp, _Args...>>;
516 
517 template <class _Fn, class... _Args>
518 concept __minvocable_succeeds =
519     __minvocable<_Fn, _Args...> && __ok<__minvoke<_Fn, _Args...>>;
520 
521 template <class _Fn, class... _Args>
522 struct __minvoke_force_
523 {
524     using __t = __minvoke<_Fn, _Args...>;
525 };
526 template <class _Fn, class... _Args>
527 using __minvoke_force = __t<__minvoke_force_<_Fn, _Args...>>;
528 
529 template <class _Fn, class... _Args>
530 struct __mdefer_
531 {};
532 
533 template <class _Fn, class... _Args>
534     requires __minvocable<_Fn, _Args...>
535 struct __mdefer_<_Fn, _Args...>
536 {
537     using __t = __minvoke<_Fn, _Args...>;
538 };
539 
540 template <class _Fn, class... _Args>
541 struct __mdefer : __mdefer_<_Fn, _Args...>
542 {};
543 
544 template <class _Fn, class... _Args>
545 using __mmemoize = __t<__mdefer<_Fn, _Args...>>;
546 
547 template <template <class...> class _Fn, class... _Args>
548 using __mmemoize_q = __mmemoize<__q<_Fn>, _Args...>;
549 
550 struct __if_
551 {
552     template <bool>
553     struct __
554     {
555         template <class _True, class...>
556         using __f = _True;
557     };
558 
559     template <class _Pred, class _True, class... _False>
560     using __f = __minvoke<__<static_cast<bool>(__v<_Pred>)>, _True, _False...>;
561 };
562 
563 template <>
564 struct __if_::__<false>
565 {
566     template <class, class _False>
567     using __f = _False;
568 };
569 
570 template <class _Pred, class _True = void, class... _False>
571     requires(sizeof...(_False) <= 1)
572 using __if = __minvoke<__if_, _Pred, _True, _False...>;
573 
574 template <bool _Pred, class _True = void, class... _False>
575     requires(sizeof...(_False) <= 1)
576 using __if_c = __minvoke<__if_::__<_Pred>, _True, _False...>;
577 
578 template <class _Pred, class _True, class _False, class... _Args>
579 using __minvoke_if = __minvoke<__if<_Pred, _True, _False>, _Args...>;
580 
581 template <bool _Pred, class _True, class _False, class... _Args>
582 using __minvoke_if_c = __minvoke<__if_c<_Pred, _True, _False>, _Args...>;
583 
584 template <class _Tp>
585 struct __mconst
586 {
587     template <class...>
588     using __f = _Tp;
589 };
590 
591 inline constexpr __mstring __mbad_substitution =
592     "The specified meta-function could not be evaluated with the types provided."_mstr;
593 
594 template <__mstring _Diagnostic = __mbad_substitution>
595 struct _BAD_SUBSTITUTION_
596 {};
597 
598 template <class... _Args>
599 struct _WITH_TYPES_;
600 
601 template <template <class...> class _Fun>
602 struct _WITH_META_FUNCTION_T_
603 {
604     template <class... _Args>
605     using __f = __mexception<_BAD_SUBSTITUTION_<>, _WITH_META_FUNCTION_T_,
606                              _WITH_TYPES_<_Args...>>;
607 };
608 
609 template <class _Fun>
610 struct _WITH_META_FUNCTION_
611 {
612     template <class... _Args>
613     using __f = __mexception<_BAD_SUBSTITUTION_<>, _WITH_META_FUNCTION_,
614                              _WITH_TYPES_<_Args...>>;
615 };
616 
617 template <template <class...> class _Try, class _Catch>
618 struct __mtry_catch_q
619 {
620     template <class... _Args>
621     using __f = __minvoke<__if_c<__mvalid<_Try, _Args...>, __q<_Try>, _Catch>,
622                           _Args...>;
623 };
624 
625 template <class _Try, class _Catch>
626 struct __mtry_catch
627 {
628     template <class... _Args>
629     using __f =
630         __minvoke<__if_c<__minvocable<_Try, _Args...>, _Try, _Catch>, _Args...>;
631 };
632 
633 template <class _Fn, class _Default>
634 using __with_default = __mtry_catch<_Fn, __mconst<_Default>>;
635 
636 template <template <class...> class _Fn, class _Default>
637 using __with_default_q = __mtry_catch_q<_Fn, __mconst<_Default>>;
638 
639 template <class _Fn, class _Default, class... _Args>
640 using __minvoke_or = __minvoke<__with_default<_Fn, _Default>, _Args...>;
641 
642 template <template <class...> class _Fn, class _Default, class... _Args>
643 using __meval_or = __minvoke<__with_default_q<_Fn, _Default>, _Args...>;
644 
645 template <template <class...> class _Fn>
646 struct __mtry_eval_
647 {
648     template <class... _Args>
649     using __f = __meval<_Fn, _Args...>;
650 };
651 
652 template <template <class...> class _Fn, class... _Args>
653 using __mtry_eval =
654     __minvoke<__mtry_catch<__mtry_eval_<_Fn>, _WITH_META_FUNCTION_T_<_Fn>>,
655               _Args...>;
656 
657 template <class _Fn, class... _Args>
658 using __mtry_invoke =
659     __minvoke<__mtry_catch<_Fn, _WITH_META_FUNCTION_<_Fn>>, _Args...>;
660 
661 template <class _Ty, class... _Default>
662 using __msuccess_or_t = __if_c<__ok<_Ty>, _Ty, _Default...>;
663 
664 template <class _Ty, class... _Default>
665 using __merror_or_t = __if_c<__merror<_Ty>, _Ty, _Default...>;
666 
667 template <class _Fn, class _Continuation = __q<__types>>
668 struct __mtransform
669 {
670     template <class... _Args>
671     using __f = __minvoke<_Continuation, __minvoke<_Fn, _Args>...>;
672 };
673 
674 template <bool>
675 struct __mfold_right_
676 {
677     template <class _Fn, class _State, class _Head, class... _Tail>
678     using __f = __minvoke<__mfold_right_<sizeof...(_Tail) == 0>, _Fn,
679                           __minvoke<_Fn, _State, _Head>, _Tail...>;
680 };
681 
682 template <>
683 struct __mfold_right_<true>
684 { // empty pack
685     template <class _Fn, class _State, class...>
686     using __f = _State;
687 };
688 
689 template <class _Init, class _Fn>
690 struct __mfold_right
691 {
692     template <class... _Args>
693     using __f =
694         __minvoke<__mfold_right_<sizeof...(_Args) == 0>, _Fn, _Init, _Args...>;
695 };
696 
697 template <bool>
698 struct __mfold_left_
699 {
700     template <class _Fn, class _State, class _Head, class... _Tail>
701     using __f = __minvoke<
702         _Fn,
703         __mcall<__mfold_left_<sizeof...(_Tail) == 0>, _Fn, _State, _Tail...>,
704         _Head>;
705 };
706 
707 template <>
708 struct __mfold_left_<true>
709 { // empty pack
710     template <class _Fn, class _State, class...>
711     using __f = _State;
712 };
713 
714 template <class _Init, class _Fn>
715 struct __mfold_left
716 {
717     template <class... _Args>
718     using __f =
719         __minvoke<__mfold_left_<sizeof...(_Args) == 0>, _Fn, _Init, _Args...>;
720 };
721 
722 template <class _Fn>
723 struct __mcurry
724 {
725     template <class... _Ts>
726     using __f = __minvoke<_Fn, _Ts...>;
727 };
728 
729 template <class _Tp>
730 struct __muncurry_;
731 
732 template <template <class...> class _Ap, class... _As>
733 struct __muncurry_<_Ap<_As...>>
734 {
735     template <class _Fn>
736     using __f = __minvoke<_Fn, _As...>;
737 };
738 
739 template <class _What, class... _With>
740 struct __muncurry_<_ERROR_<_What, _With...>>
741 {
742     template <class _Fn>
743     using __f = _ERROR_<_What, _With...>;
744 };
745 
746 template <class _Fn>
747 struct __muncurry
748 {
749     template <class _Tp>
750     using __f = typename __muncurry_<_Tp>::template __f<_Fn>;
751 };
752 
753 template <class _Fn, class _List>
754 using __mapply = __minvoke<__muncurry<_Fn>, _List>;
755 
756 template <bool>
757 struct __mconcat_
758 {
759     template <class... _Ts, template <class...> class _Ap = __types,
760               class... _As, template <class...> class _Bp = __types,
761               class... _Bs, template <class...> class _Cp = __types,
762               class... _Cs, template <class...> class _Dp = __types,
763               class... _Ds, class... _Tail>
764     static auto __f(__types<_Ts...>*, _Ap<_As...>*, _Bp<_Bs...>* = nullptr,
765                     _Cp<_Cs...>* = nullptr, _Dp<_Ds...>* = nullptr,
766                     _Tail*... __tail)
767         -> decltype(__mconcat_<(sizeof...(_Tail) == 0)>::__f(
768             static_cast<__types<_Ts..., _As..., _Bs..., _Cs..., _Ds...>*>(
769                 nullptr),
770             __tail...));
771 };
772 
773 template <>
774 struct __mconcat_<true>
775 {
776     template <class... _As>
777     static auto __f(__types<_As...>*) -> __types<_As...>;
778 };
779 
780 template <class _Continuation = __qq<__types>>
781 struct __mconcat
782 {
783     template <class... _Args>
784     using __f = __mapply<_Continuation,
785                          decltype(__mconcat_<(sizeof...(_Args) == 0)>::__f(
786                              {}, static_cast<_Args*>(nullptr)...))>;
787 };
788 
789 struct __msize
790 {
791     template <class... _Ts>
792     using __f = __msize_t<sizeof...(_Ts)>;
793 };
794 
795 template <class _Ty>
796 struct __mcount
797 {
798     template <class... _Ts>
799     using __f = __msize_t<(__same_as<_Ts, _Ty> + ... + 0)>;
800 };
801 
802 template <class _Fn>
803 struct __mcount_if
804 {
805     template <class... _Ts>
806     using __f = __msize_t<(bool(__v<__minvoke<_Fn, _Ts>>) + ... + 0)>;
807 };
808 
809 template <class _Tp>
810 struct __mcontains
811 {
812     template <class... _Args>
813     using __f = __mbool<(__same_as<_Tp, _Args> || ...)>;
814 };
815 
816 template <class _Continuation = __q<__types>>
817 struct __mpush_back
818 {
819     template <class _List, class _Item>
820     using __f = __mapply<__mbind_back<_Continuation, _Item>, _List>;
821 };
822 
823 template <class...>
824 struct __mcompose
825 {};
826 
827 template <class _First>
828 struct __mcompose<_First> : _First
829 {};
830 
831 template <class _Second, class _First>
832 struct __mcompose<_Second, _First>
833 {
834     template <class... _Args>
835     using __f = __minvoke<_Second, __minvoke<_First, _Args...>>;
836 };
837 
838 template <class _Last, class _Penultimate, class... _Rest>
839 struct __mcompose<_Last, _Penultimate, _Rest...>
840 {
841     template <class... _Args>
842     using __f =
843         __minvoke<_Last,
844                   __minvoke<__mcompose<_Penultimate, _Rest...>, _Args...>>;
845 };
846 
847 template <template <class...> class _Second, template <class...> class _First>
848 struct __mcompose_q
849 {
850     template <class... _Args>
851     using __f = _Second<_First<_Args...>>;
852 };
853 
854 template <class _Old, class _New, class _Continuation = __q<__types>>
855 struct __mreplace
856 {
857     template <class... _Args>
858     using __f = __minvoke<_Continuation,
859                           __if_c<__same_as<_Args, _Old>, _New, _Args>...>;
860 };
861 
862 template <class _Old, class _Continuation = __q<__types>>
863 struct __mremove
864 {
865     template <class... _Args>
866     using __f = //
867         __minvoke<__mconcat<_Continuation>,
868                   __if_c<__same_as<_Args, _Old>, __types<>, __types<_Args>>...>;
869 };
870 
871 template <class _Pred, class _Continuation = __q<__types>>
872 struct __mremove_if
873 {
874     template <class... _Args>
875     using __f = //
876         __minvoke<__mconcat<_Continuation>,
877                   __if<__minvoke<_Pred, _Args>, __types<>, __types<_Args>>...>;
878 };
879 
880 template <class _Return>
881 struct __qf
882 {
883     template <class... _Args>
884     using __f = _Return(_Args...);
885 };
886 
887 template <class _Ty, class...>
888 using __mfront_ = _Ty;
889 template <class... _As>
890 using __mfront = __meval<__mfront_, _As...>;
891 template <class... _As>
892     requires(sizeof...(_As) == 1)
893 using __msingle = __mfront<_As...>;
894 template <class _Default, class... _As>
895     requires(sizeof...(_As) <= 1)
896 using __msingle_or_ = __mfront<_As..., _Default>;
897 template <class _Default>
898 using __msingle_or = __mbind_front_q<__msingle_or_, _Default>;
899 
900 template <class _Ty>
901 concept __has_id = requires { typename _Ty::__id; };
902 
903 template <class _Ty>
904 struct _Id
905 {
906     using __t = _Ty;
907 
908     // Uncomment the line below to find any code that likely misuses the
909     // ADL isolation mechanism. In particular, '__id<T>' when T is a
910     // reference is a likely misuse. The static_assert below will trigger
911     // when the type passed to the __id alias template is a reference to
912     // a type that is setup to use ADL isolation.
913     // static_assert(!__has_id<std::remove_cvref_t<_Ty>>);
914 };
915 
916 template <bool = true>
917 struct __id_
918 {
919     template <class _Ty>
920     using __f = typename _Ty::__id;
921 };
922 
923 template <>
924 struct __id_<false>
925 {
926     template <class _Ty>
927     using __f = _Id<_Ty>;
928 };
929 template <class _Ty>
930 using __id = __minvoke<__id_<__has_id<_Ty>>, _Ty>;
931 
932 template <class _From, class _To = __decay_t<_From>>
933 using __cvref_t = __copy_cvref_t<_From, __t<_To>>;
934 
935 template <class _From, class _To = __decay_t<_From>>
936 using __cvref_id = __copy_cvref_t<_From, __id<_To>>;
937 
938 #if STDEXEC_NVHPC()
939 // nvc++ doesn't cache the results of alias template specializations.
940 // To avoid repeated computation of the same function return type,
941 // cache the result ourselves in a class template specialization.
942 template <class _Fun, class... _As>
943 using __call_result_ = decltype(__declval<_Fun>()(__declval<_As>()...));
944 template <class _Fun, class... _As>
945 using __call_result_t = __t<__mdefer<__q<__call_result_>, _Fun, _As...>>;
946 #else
947 template <class _Fun, class... _As>
948 using __call_result_t = decltype(__declval<_Fun>()(__declval<_As>()...));
949 #endif
950 
951 // BUGBUG TODO file this bug with nvc++
952 #if STDEXEC_NVHPC()
953 template <const auto& _Fun, class... _As>
954 using __result_of = __call_result_t<decltype(_Fun), _As...>;
955 #else
956 template <const auto& _Fun, class... _As>
957 using __result_of = decltype(_Fun(__declval<_As>()...));
958 #endif
959 
960 template <const auto& _Fun, class... _As>
961 inline constexpr bool __noexcept_of = noexcept(_Fun(__declval<_As>()...));
962 
963 // For emplacing non-movable types into optionals:
964 template <class _Fn>
965     requires std::is_nothrow_move_constructible_v<_Fn>
966 struct __emplace_from
967 {
968     _Fn __fn_;
969     using __t = __call_result_t<_Fn>;
970 
operator __tstdexec::__emplace_from971     operator __t() && noexcept(__nothrow_callable<_Fn>)
972     {
973         return static_cast<_Fn&&>(__fn_)();
974     }
975 
operator ()stdexec::__emplace_from976     auto operator()() && noexcept(__nothrow_callable<_Fn>) -> __t
977     {
978         return static_cast<_Fn&&>(__fn_)();
979     }
980 };
981 
982 template <class _Fn>
983 __emplace_from(_Fn) -> __emplace_from<_Fn>;
984 
985 template <class, class, class, class>
986 struct __mzip_with2_;
987 
988 template <               //
989     class _Fn,           //
990     class _Continuation, //
991     template <class...> class _Cp,
992     class... _Cs,        //
993     template <class...> class _Dp, class... _Ds>
994     requires requires {
995                  typename __minvoke<_Continuation, __minvoke<_Fn, _Cs, _Ds>...>;
996              }
997 struct __mzip_with2_<_Fn, _Continuation, _Cp<_Cs...>, _Dp<_Ds...>>
998 {
999     using __t = __minvoke<_Continuation, __minvoke<_Fn, _Cs, _Ds>...>;
1000 };
1001 
1002 template <class _Fn, class _Continuation = __q<__types>>
1003 struct __mzip_with2
1004 {
1005     template <class _Cp, class _Dp>
1006     using __f = __t<__mzip_with2_<_Fn, _Continuation, _Cp, _Dp>>;
1007 };
1008 
1009 template <bool>
1010 struct __mfind_if_
1011 {
1012     template <class _Fn, class _Continuation, class _Head, class... _Tail>
1013     using __f = //
1014         __minvoke<__if_c<__v<__minvoke<_Fn, _Head>>,
1015                          __mbind_front<_Continuation, _Head>,
1016                          __mbind_front<__mfind_if_<(sizeof...(_Tail) != 0)>,
1017                                        _Fn, _Continuation>>,
1018                   _Tail...>;
1019 };
1020 
1021 template <>
1022 struct __mfind_if_<false>
1023 {
1024     template <class _Fn, class _Continuation>
1025     using __f = __minvoke<_Continuation>;
1026 };
1027 
1028 template <class _Fn, class _Continuation = __q<__types>>
1029 struct __mfind_if
1030 {
1031     template <class... _Args>
1032     using __f = __minvoke<__mfind_if_<(sizeof...(_Args) != 0)>, _Fn,
1033                           _Continuation, _Args...>;
1034 };
1035 
1036 template <class _Fn>
1037 struct __mfind_if_i
1038 {
1039     template <class... _Args>
1040     using __f = __msize_t<(
1041         sizeof...(_Args) - __v<__minvoke<__mfind_if<_Fn, __msize>, _Args...>>)>;
1042 };
1043 
1044 #if STDEXEC_MSVC()
1045 #define __mvalue_of(...) __VA_ARGS__::value
1046 #else
1047 #define __mvalue_of(...) __v<__VA_ARGS__>
1048 #endif
1049 
1050 template <class... _Booleans>
1051 using __mand_t = __mbool<(__mvalue_of(_Booleans) && ...)>;
1052 template <class... _Booleans>
1053 using __mand = __meval<__mand_t, _Booleans...>;
1054 
1055 template <class... _Booleans>
1056 using __mor_t = __mbool<(__mvalue_of(_Booleans) || ...)>;
1057 template <class... _Booleans>
1058 using __mor = __meval<__mor_t, _Booleans...>;
1059 
1060 template <class _Boolean>
1061 using __mnot_t = __mbool<!__mvalue_of(_Boolean)>;
1062 template <class _Boolean>
1063 using __mnot = __meval<__mnot_t, _Boolean>;
1064 
1065 #if STDEXEC_NVHPC()
1066 template <class... _Ints>
1067 struct __mplus_t : __mconstant<(__v<_Ints> + ...)>
1068 {};
1069 #else
1070 template <class... _Ints>
1071 using __mplus_t = __mconstant<(__mvalue_of(_Ints) + ...)>;
1072 #endif
1073 
1074 #undef __mvalue_of
1075 
1076 template <class _Fn>
1077 struct __mall_of
1078 {
1079     template <class... _Args>
1080     using __f = __mand<__minvoke<_Fn, _Args>...>;
1081 };
1082 
1083 template <class _Fn>
1084 struct __mnone_of
1085 {
1086     template <class... _Args>
1087     using __f = __mand<__mnot<__minvoke<_Fn, _Args>>...>;
1088 };
1089 
1090 template <class _Fn>
1091 struct __many_of
1092 {
1093     template <class... _Args>
1094     using __f = __mor<__minvoke<_Fn, _Args>...>;
1095 };
1096 
1097 #if defined(__cpp_pack_indexing)
1098 template <class _Np, class... _Ts>
1099 using __m_at = _Ts...[__v<_Np>];
1100 
1101 template <std::size_t _Np, class... _Ts>
1102 using __m_at_c = _Ts...[_Np];
1103 #elif STDEXEC_HAS_BUILTIN(__type_pack_element)
1104 template <bool>
1105 struct __m_at_
1106 {
1107     template <class _Np, class... _Ts>
1108     using __f = __type_pack_element<__v<_Np>, _Ts...>;
1109 };
1110 
1111 template <class _Np, class... _Ts>
1112 using __m_at = __minvoke<__m_at_<__v<_Np> == ~0ul>, _Np, _Ts...>;
1113 
1114 template <std::size_t _Np, class... _Ts>
1115 using __m_at_c = __minvoke<__m_at_<_Np == ~0ul>, __msize_t<_Np>, _Ts...>;
1116 #else
1117 template <std::size_t>
1118 using __void_ptr = void*;
1119 
1120 template <class _Ty>
1121 using __mtype_ptr = __mtype<_Ty>*;
1122 
1123 template <class _Ty>
1124 struct __m_at_;
1125 
1126 template <std::size_t... _Is>
1127 struct __m_at_<__indices<_Is...>>
1128 {
1129     template <class _Up, class... _Us>
1130     static _Up __f_(__void_ptr<_Is>..., _Up*, _Us*...);
1131     template <class... _Ts>
1132     using __f = __t<decltype(__m_at_::__f_(__mtype_ptr<_Ts>()...))>;
1133 };
1134 
1135 template <std::size_t _Np, class... _Ts>
1136 using __m_at_c = __minvoke<__m_at_<__make_indices<_Np>>, _Ts...>;
1137 
1138 template <class _Np, class... _Ts>
1139 using __m_at = __m_at_c<__v<_Np>, _Ts...>;
1140 #endif
1141 
1142 template <class... _Ts>
1143 using __mback = __m_at_c<sizeof...(_Ts) - 1, _Ts...>;
1144 
1145 template <class _Continuation = __q<__types>>
1146 struct __mpop_back
1147 {
1148     template <class>
1149     struct __impl;
1150 
1151     template <std::size_t... _Idx>
1152     struct __impl<__indices<_Idx...>>
1153     {
1154         template <class... _Ts>
1155         using __f = __minvoke<_Continuation, __m_at_c<_Idx, _Ts...>...>;
1156     };
1157 
1158     template <class... _Ts>
1159         requires(sizeof...(_Ts) != 0)
1160     using __f = __minvoke<__impl<__make_indices<sizeof...(_Ts) - 1>>, _Ts...>;
1161 };
1162 
1163 template <std::size_t _Np>
1164 struct __placeholder
1165 {
1166     __placeholder() = default;
1167 
__placeholderstdexec::__placeholder1168     constexpr __placeholder(void*) noexcept {}
1169 
1170     constexpr friend auto
__get_placeholder_offset(__placeholder)1171         __get_placeholder_offset(__placeholder) noexcept -> std::size_t
1172     {
1173         return _Np;
1174     }
1175 };
1176 
1177 using __0 = __placeholder<0>;
1178 using __1 = __placeholder<1>;
1179 using __2 = __placeholder<2>;
1180 using __3 = __placeholder<3>;
1181 
1182 #if defined(__cpp_pack_indexing)
1183 template <std::size_t _Np>
1184 struct __nth_pack_element_t
1185 {
1186     template <class... _Ts>
1187     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_pack_element_t1188     constexpr decltype(auto) operator()(_Ts&&... __ts) const noexcept
1189     {
1190         static_assert(_Np < sizeof...(_Ts));
1191         return (static_cast<_Ts&&>(__ts)...[_Np]);
1192     }
1193 };
1194 #else
1195 template <class... _Ignore>
1196 struct __nth_pack_element_impl
1197 {
1198     template <class _Ty, class... _Us>
1199     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_pack_element_impl1200     constexpr _Ty&& operator()(_Ignore..., _Ty&& __t, _Us&&...) const noexcept
1201     {
1202         return static_cast<decltype(__t)&&>(__t);
1203     }
1204 };
1205 
1206 template <std::size_t _Np>
1207 struct __nth_pack_element_t
1208 {
1209     template <std::size_t... _Is>
1210     STDEXEC_ATTRIBUTE((always_inline))
__implstdexec::__nth_pack_element_t1211     static constexpr auto __impl(__indices<_Is...>) noexcept
1212     {
1213         return __nth_pack_element_impl<__ignore_t<_Is>...>();
1214     }
1215 
1216     template <class... _Ts>
1217     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_pack_element_t1218     constexpr decltype(auto) operator()(_Ts&&... __ts) const noexcept
1219     {
1220         static_assert(_Np < sizeof...(_Ts));
1221         return __impl(__make_indices<_Np>())(static_cast<_Ts&&>(__ts)...);
1222     }
1223 };
1224 #endif
1225 
1226 template <std::size_t _Np>
1227 inline constexpr __nth_pack_element_t<_Np> __nth_pack_element{};
1228 
1229 template <auto... _Vs>
1230 struct __mliterals
1231 {
1232     template <std::size_t _Np>
1233     STDEXEC_ATTRIBUTE((always_inline))
__nthstdexec::__mliterals1234     static constexpr auto __nth() noexcept
1235     {
1236         return stdexec::__nth_pack_element<_Np>(_Vs...);
1237     }
1238 };
1239 
1240 template <std::size_t _Np>
1241 struct __nth_member
1242 {
1243     template <class _Ty>
1244     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_member1245     constexpr decltype(auto) operator()(_Ty&& __ty) const noexcept
1246     {
1247         return static_cast<_Ty&&>(__ty).*(__ty.__mbrs_.template __nth<_Np>());
1248     }
1249 };
1250 
1251 template <class _Ty, std::size_t _Offset = 0>
1252 struct __mdispatch_
1253 {
1254     template <class... _Ts>
operator ()stdexec::__mdispatch_1255     auto operator()(_Ts&&...) const noexcept(noexcept(_Ty{})) -> _Ty
1256     {
1257         return _Ty{};
1258     }
1259 };
1260 
1261 template <std::size_t _Np, std::size_t _Offset>
1262 struct __mdispatch_<__placeholder<_Np>, _Offset>
1263 {
1264     template <class... _Ts>
operator ()stdexec::__mdispatch_1265     auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1266     {
1267         return stdexec::__nth_pack_element<_Np + _Offset>(
1268             static_cast<_Ts&&>(__ts)...);
1269     }
1270 };
1271 
1272 template <std::size_t _Np, std::size_t _Offset>
1273 struct __mdispatch_<__placeholder<_Np>&, _Offset>
1274 {
1275     template <class... _Ts>
operator ()stdexec::__mdispatch_1276     auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1277     {
1278         return stdexec::__nth_pack_element<_Np + _Offset>(__ts...);
1279     }
1280 };
1281 
1282 template <std::size_t _Np, std::size_t _Offset>
1283 struct __mdispatch_<__placeholder<_Np>&&, _Offset>
1284 {
1285     template <class... _Ts>
operator ()stdexec::__mdispatch_1286     auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1287     {
1288         return std::move(stdexec::__nth_pack_element<_Np + _Offset>(__ts...));
1289     }
1290 };
1291 
1292 template <std::size_t _Np, std::size_t _Offset>
1293 struct __mdispatch_<const __placeholder<_Np>&, _Offset>
1294 {
1295     template <class... _Ts>
operator ()stdexec::__mdispatch_1296     auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1297     {
1298         return std::as_const(
1299             stdexec::__nth_pack_element<_Np + _Offset>(__ts...));
1300     }
1301 };
1302 
1303 template <class _Ret, class... _Args, std::size_t _Offset>
1304 struct __mdispatch_<_Ret (*)(_Args...), _Offset>
1305 {
1306     template <class... _Ts>
1307         requires(__callable<__mdispatch_<_Args, _Offset>, _Ts...> && ...) &&
1308                     __callable<_Ret,
1309                                __call_result_t<__mdispatch_<_Args, _Offset>,
1310                                                _Ts...>...>
operator ()stdexec::__mdispatch_1311     auto operator()(_Ts&&... __ts) const noexcept(
1312         __nothrow_callable<
1313             _Ret, __call_result_t<__mdispatch_<_Args, _Offset>, _Ts...>...>)
1314         -> __call_result_t<
1315             _Ret, __call_result_t<__mdispatch_<_Args, _Offset>, _Ts...>...>
1316     {
1317         return _Ret{}(
1318             __mdispatch_<_Args, _Offset>{}(static_cast<_Ts&&>(__ts)...)...);
1319     }
1320 };
1321 
1322 template <class _Ret, class... _Args, std::size_t _Offset>
1323 struct __mdispatch_<_Ret (*)(_Args..., ...), _Offset>
1324 {
1325     static_assert(_Offset == 0, "nested pack expressions are not supported");
1326     using _Pattern = __mback<_Args...>;
1327     static constexpr std::size_t __offset =
1328         __get_placeholder_offset(static_cast<__mtype<_Pattern>*>(nullptr));
1329 
1330     struct __impl
1331     {
1332         template <std::size_t... _Idx, class... _Ts>
1333             requires(__callable<__mdispatch_<_Args>, _Ts...> && ...) &&
1334                         (__callable<__mdispatch_<_Pattern, _Idx + 1>, _Ts...> &&
1335                          ...) &&
1336                         __callable< //
1337                             _Ret,
1338                             __call_result_t<__mdispatch_<_Args>, _Ts...>...,
1339                             __call_result_t<__mdispatch_<_Pattern, _Idx + 1>,
1340                                             _Ts...>...>
operator ()stdexec::__mdispatch_::__impl1341         auto operator()(__indices<_Idx...>, _Ts&&... __ts) const noexcept(
1342             __nothrow_callable<                                  //
1343                 _Ret,                                            //
1344                 __call_result_t<__mdispatch_<_Args>, _Ts...>..., //
1345                 __call_result_t<__mdispatch_<_Pattern, _Idx + 1>, _Ts...>...>)
1346             -> __call_result_t<                                  //
1347                 _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...,
1348                 __call_result_t<__mdispatch_<_Pattern, _Idx + 1>, _Ts...>...>
1349         {
1350             return _Ret()(                                             //
1351                 __mdispatch_<_Args>()(static_cast<_Ts&&>(__ts)...)..., //
1352                 __mdispatch_<_Pattern, _Idx + 1>()(
1353                     static_cast<_Ts&&>(__ts)...)...);
1354         }
1355     };
1356 
1357     template <class... _Ts>
1358         requires(__offset < sizeof...(_Ts)) &&
1359                     __callable<__impl,
1360                                __make_indices<sizeof...(_Ts) - __offset - 1>,
1361                                _Ts...>
operator ()stdexec::__mdispatch_1362     auto operator()(_Ts&&... __ts) const noexcept(
1363         __nothrow_callable<
1364             __impl, __make_indices<sizeof...(_Ts) - __offset - 1>, _Ts...>)
1365         -> __msecond<
1366             __if_c<(__offset < sizeof...(_Ts))>,
1367             __call_result_t<
1368                 __impl, __make_indices<sizeof...(_Ts) - __offset - 1>, _Ts...>>
1369     {
1370         return __impl()(__make_indices<sizeof...(_Ts) - __offset - 1>(),
1371                         static_cast<_Ts&&>(__ts)...);
1372     }
1373 
1374     template <class... _Ts>
1375         requires(sizeof...(_Ts) == __offset) &&
1376                     __callable<__mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>,
1377                                                       _Args...>*>,
1378                                _Ts...>
operator ()stdexec::__mdispatch_1379     auto operator()(_Ts&&... __ts) const //
1380         noexcept(__nothrow_callable<
1381                  __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>,
1382                  _Ts...>)
1383             -> __msecond<
1384                 __if_c<(sizeof...(_Ts) == __offset)>,
1385                 __call_result_t<
1386                     __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>,
1387                     _Ts...>>
1388     {
1389         return __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>()(
1390             static_cast<_Ts&&>(__ts)...);
1391     }
1392 };
1393 
1394 template <class _Ty>
1395 struct __mdispatch
1396 {};
1397 
1398 template <class _Ret, class... _Args>
1399 struct __mdispatch<_Ret(_Args...)> : __mdispatch_<_Ret (*)(_Args...)>
1400 {};
1401 
1402 template <class _Ret, class... _Args>
1403 struct __mdispatch<_Ret(_Args..., ...)> : __mdispatch_<_Ret (*)(_Args..., ...)>
1404 {};
1405 
1406 template <class _Ty, class... _Ts>
1407 concept __dispatchable = __callable<__mdispatch<_Ty>, _Ts...>;
1408 
1409 template <class _Ty, class... _Ts>
1410 concept __nothrow_dispatchable = __nothrow_callable<__mdispatch<_Ty>, _Ts...>;
1411 
1412 template <class _Ty, class... _Ts>
1413 using __dispatch_result_t = __call_result_t<__mdispatch<_Ty>, _Ts...>;
1414 
1415 template <class _Signature, class... _Args>
1416 using __try_dispatch_ = __mbool<__dispatchable<_Signature, _Args...>>;
1417 
1418 template <class _Signatures, class _Continuation = __q<__mfront>>
1419 struct __which
1420 {};
1421 
1422 template <template <class...> class _Cp, class... _Signatures,
1423           class _Continuation>
1424 struct __which<_Cp<_Signatures...>, _Continuation>
1425 {
1426     template <class... _Args>
1427     using __f = //
1428         __minvoke<__mfind_if<__mbind_back_q<__try_dispatch_, _Args...>,
1429                              _Continuation>,
1430                   _Signatures...>;
1431 };
1432 
1433 template <class _Signatures, class _DefaultFn, class... _Args>
1434 using __make_dispatcher = //
1435     __minvoke<__mtry_catch<__mcompose<__q<__mdispatch>, __which<_Signatures>>,
1436                            _DefaultFn>,
1437               _Args...>;
1438 
1439 template <class _Set, class... _Ty>
1440 concept __mset_contains = (STDEXEC_IS_BASE_OF(__mtype<_Ty>, _Set) && ...);
1441 
1442 namespace __set
1443 {
1444 template <class... _Ts>
1445 struct __inherit
1446 {};
1447 
1448 template <class _Ty, class... _Ts>
1449 struct __inherit<_Ty, _Ts...> : __mtype<_Ty>, __inherit<_Ts...>
1450 {};
1451 
1452 template <class... _Set>
1453 auto operator+(__inherit<_Set...>&) -> __inherit<_Set...>;
1454 
1455 template <class... _Set, class _Ty>
1456 auto operator%(__inherit<_Set...>&, __mtype<_Ty>&) //
1457     -> __if_c<                                     //
1458         __mset_contains<__inherit<_Set...>, _Ty>, __inherit<_Set...>,
1459         __inherit<_Ty, _Set...>>&;
1460 
1461 template <class _ExpectedSet, class... _Ts>
1462 concept __mset_eq =                                             //
1463     (sizeof...(_Ts) == __v<__mapply<__msize, _ExpectedSet>>) && //
1464     __mset_contains<_ExpectedSet, _Ts...>;
1465 
1466 template <class _ExpectedSet>
1467 struct __eq
1468 {
1469     template <class... _Ts>
1470     using __f = __mbool<__mset_eq<_ExpectedSet, _Ts...>>;
1471 };
1472 } // namespace __set
1473 
1474 template <class... _Ts>
1475 using __mset = __set::__inherit<_Ts...>;
1476 
1477 template <class _Set, class... _Ts>
1478 using __mset_insert =
1479     decltype(+(__declval<_Set&>() % ... % __declval<__mtype<_Ts>&>()));
1480 
1481 template <class... _Ts>
1482 using __mmake_set = __mset_insert<__mset<>, _Ts...>;
1483 
1484 template <class _Set1, class _Set2>
1485 concept __mset_eq = __v<__mapply<__set::__eq<_Set1>, _Set2>>;
1486 
1487 template <class _Continuation = __q<__types>>
1488 struct __munique
1489 {
1490     template <class... _Ts>
1491     using __f = __mapply<_Continuation, __mmake_set<_Ts...>>;
1492 };
1493 } // namespace stdexec
1494