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