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