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