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