1 /*
2 * Copyright (c) 2021-2022 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
22 #include <cassert>
23 #include <cstddef>
24 #include <exception>
25 #include <type_traits>
26 #include <utility>
27
28 namespace stdexec
29 {
30
31 template <class...>
32 struct __undefined;
33
34 struct __
35 {};
36
37 struct __ignore
38 {
39 __ignore() = default;
40
41 STDEXEC_ATTRIBUTE((always_inline))
__ignorestdexec::__ignore42 constexpr __ignore(auto&&...) noexcept {}
43 };
44
45 struct __none_such
46 {};
47
48 namespace
49 {
50 struct __anon
51 {};
52 } // namespace
53
54 struct __immovable
55 {
56 __immovable() = default;
57
58 private:
59 STDEXEC_IMMOVABLE(__immovable);
60 };
61
62 struct __move_only
63 {
64 __move_only() = default;
65
66 __move_only(__move_only&&) noexcept = default;
67 auto operator=(__move_only&&) noexcept -> __move_only& = default;
68
69 __move_only(const __move_only&) = delete;
70 auto operator=(const __move_only&) -> __move_only& = delete;
71 };
72
73 template <class _Tp>
74 using __t = typename _Tp::__t;
75
76 template <bool _Bp>
77 using __mbool = std::bool_constant<_Bp>;
78
79 template <class _Ty>
80 struct __mtype
81 {
82 using __t = _Ty;
83 };
84
85 template <auto _Value>
86 using __mtypeof = decltype(_Value);
87
88 template <class...>
89 struct __types;
90
91 template <class _Tp>
92 using __midentity = _Tp;
93
94 template <std::size_t _Np>
95 using __msize_t = char[_Np + 1];
96
97 template <auto _Np>
98 struct __mconstant_;
99
100 template <auto _Np>
101 using __mconstant = __mconstant_<_Np>*;
102
103 template <class _Tp, class _Up>
104 using __mfirst = _Tp;
105
106 template <class _Tp, class _Up>
107 using __msecond = _Up;
108
109 template <class _Tp>
110 extern const __undefined<_Tp> __v;
111
112 template <class _Tp>
113 requires __typename<__mtypeof<_Tp::value>>
114 inline constexpr auto __v<_Tp> = _Tp::value;
115
116 template <class _Tp, class _Up>
117 inline constexpr bool __v<std::is_same<_Tp, _Up>> = false;
118
119 template <class _Tp>
120 inline constexpr bool __v<std::is_same<_Tp, _Tp>> = true;
121
122 template <class _Tp, _Tp _Ip>
123 inline constexpr _Tp __v<std::integral_constant<_Tp, _Ip>> = _Ip;
124
125 template <auto _Np>
126 inline constexpr __mtypeof<_Np> __v<__mconstant<_Np>> = _Np;
127
128 template <std::size_t _Ip>
129 inline constexpr std::size_t __v<char[_Ip]> = _Ip - 1;
130
131 template <std::size_t... _Is>
132 using __indices = std::index_sequence<_Is...>*;
133
134 template <std::size_t _Np>
135 using __make_indices = std::make_index_sequence<_Np>*;
136
137 template <class... _Ts>
138 using __indices_for = __make_indices<sizeof...(_Ts)>;
139
140 template <class _Char>
141 concept __mchar = __same_as<_Char, char>;
142
143 template <std::size_t _Len>
144 class __mstring
145 {
146 template <std::size_t... _Is>
__mstring(const char (& __str)[_Len],__indices<_Is...>)147 constexpr __mstring(const char (&__str)[_Len], __indices<_Is...>) noexcept :
148 __what_{__str[_Is]...}
149 {}
150
151 public:
__mstring(const char (& __str)[_Len])152 constexpr __mstring(const char (&__str)[_Len]) noexcept :
153 __mstring{__str, __make_indices<_Len>{}}
154 {}
155
156 template <__mchar... _Char>
157 requires(sizeof...(_Char) == _Len)
__mstring(_Char...__chars)158 constexpr __mstring(_Char... __chars) noexcept : __what_{__chars...}
159 {}
160
__length()161 static constexpr auto __length() noexcept -> std::size_t
162 {
163 return _Len;
164 }
165
166 template <std::size_t... _Is>
__equal(__mstring __other,__indices<_Is...>) const167 constexpr auto __equal(__mstring __other, __indices<_Is...>) const noexcept
168 -> bool
169 {
170 return ((__what_[_Is] == __other.__what_[_Is]) && ...);
171 }
172
operator ==(__mstring __other) const173 constexpr auto operator==(__mstring __other) const noexcept -> bool
174 {
175 return __equal(__other, __make_indices<_Len>());
176 }
177
178 const char __what_[_Len];
179 };
180
181 template <std::size_t _Len>
182 __mstring(const char (&__str)[_Len]) -> __mstring<_Len>;
183
184 STDEXEC_PRAGMA_PUSH()
185 STDEXEC_PRAGMA_IGNORE_GNU("-Wuser-defined-literals")
186
187 #if STDEXEC_NVHPC() && (__EDG_VERSION__ < 604)
188 // Use a non-standard extension for older nvc++ releases
189 template <__mchar _Char, _Char... _Str>
190 [[deprecated("Use _mstr instead")]] constexpr __mstring<sizeof...(_Str)>
operator ""__csz()191 operator""__csz() noexcept
192 {
193 return {_Str...};
194 }
195
196 // Use a non-standard extension for older nvc++ releases
197 template <__mchar _Char, _Char... _Str>
operator ""_mstr()198 constexpr __mstring<sizeof...(_Str)> operator""_mstr() noexcept
199 {
200 return {_Str...};
201 }
202 #elif STDEXEC_NVHPC() && (__EDG_VERSION__ < 605)
203 // This is to work around an unfiled (by me) EDG bug that fixed in build 605
204 template <__mstring _Str>
205 [[deprecated("Use _mstr instead")]] constexpr const __mtypeof<_Str>
206 operator""__csz() noexcept
207 {
208 return _Str;
209 }
210
211 // This is to work around an unfiled (by me) EDG bug that fixed in build 605
212 template <__mstring _Str>
213 constexpr const __mtypeof<_Str> operator""_mstr() noexcept
214 {
215 return _Str;
216 }
217 #else
218 // Use a standard user-defined string literal template
219 template <__mstring _Str>
220 [[deprecated("Use _mstr instead")]] constexpr auto operator""__csz() noexcept
221 -> __mtypeof<_Str>
222 {
223 return _Str;
224 }
225
226 // Use a standard user-defined string literal template
227 template <__mstring _Str>
228 constexpr auto operator""_mstr() noexcept -> __mtypeof<_Str>
229 {
230 return _Str;
231 }
232 #endif
233
234 STDEXEC_PRAGMA_POP()
235
236 using __msuccess = int;
237
238 template <class _What, class... _With>
239 struct _WARNING_
240 {};
241
242 template <class _What, class... _With>
243 struct _ERROR_
244 {
245 auto operator,(__msuccess) const noexcept -> _ERROR_;
246 };
247
248 template <__mstring _What>
249 struct _WHAT_
250 {};
251
252 template <class _What, class... _With>
253 using __mexception = _ERROR_<_What, _With...>;
254
255 template <class>
256 extern __msuccess __ok_v;
257
258 template <class _What, class... _With>
259 extern _ERROR_<_What, _With...> __ok_v<__mexception<_What, _With...>>;
260
261 template <class _Ty>
262 using __ok_t = decltype(__ok_v<_Ty>);
263
264 template <class... _Ts>
265 using __disp = decltype((__msuccess(), ..., __ok_t<_Ts>()));
266
267 template <class _Arg>
268 concept __ok = __same_as<__ok_t<_Arg>, __msuccess>;
269
270 template <class _Arg>
271 concept __merror = !__ok<_Arg>;
272
273 template <class... _Args>
274 concept _Ok = (__ok<_Args> && ...);
275
276 template <bool _AllOK>
277 struct __i;
278
279 #if STDEXEC_NVHPC()
280 // Most compilers memoize alias template specializations, but
281 // nvc++ does not. So we memoize the type computations by
282 // indirecting through a class template specialization.
283 template <template <class...> class _Fn, class... _Args>
284 using __meval__ = typename __i<_Ok<_Args...>>::template __g<_Fn, _Args...>;
285
286 template <template <class...> class _Fn, class... _Args>
287 struct __meval_
288 {};
289
290 template <template <class...> class _Fn, class... _Args>
291 requires __typename<__meval__<_Fn, _Args...>>
292 struct __meval_<_Fn, _Args...>
293 {
294 using __t = __meval__<_Fn, _Args...>;
295 };
296
297 template <template <class...> class _Fn, class... _Args>
298 using __meval = __t<__meval_<_Fn, _Args...>>;
299
300 template <class _Fn, class... _Args>
301 using __minvoke__ = typename __i<_Ok<_Fn>>::template __h<_Fn, _Args...>;
302
303 template <class _Fn, class... _Args>
304 struct __minvoke_
305 {};
306
307 template <class _Fn, class... _Args>
308 requires __typename<__minvoke__<_Fn, _Args...>>
309 struct __minvoke_<_Fn, _Args...>
310 {
311 using __t = __minvoke__<_Fn, _Args...>;
312 };
313
314 template <class _Fn, class... _Args>
315 using __minvoke = __t<__minvoke_<_Fn, _Args...>>;
316
317 #else
318
319 template <template <class...> class _Fn, class... _Args>
320 using __meval = typename __i<_Ok<_Args...>>::template __g<_Fn, _Args...>;
321
322 template <class _Fn, class... _Args>
323 using __minvoke = typename __i<_Ok<_Fn>>::template __h<_Fn, _Args...>;
324
325 #endif
326
327 template <bool _AllOK>
328 struct __i
329 {
330 template <template <class...> class _Fn, class... _Args>
331 using __g = _Fn<_Args...>;
332
333 template <class _Fn, class... _Args>
334 using __h = __meval<_Fn::template __f, _Args...>;
335 };
336
337 template <>
338 struct __i<false>
339 {
340 template <template <class...> class, class... _Args>
341 using __g = __disp<_Args...>;
342
343 template <class _Fn, class...>
344 using __h = _Fn;
345 };
346
347 template <template <class...> class _Fn>
348 struct __q
349 {
350 template <class... _Args>
351 using __f = __meval<_Fn, _Args...>;
352 };
353
354 template <template <class...> class _Fn, class... _Front>
355 struct __mbind_front_q
356 {
357 template <class... _Args>
358 using __f = __meval<_Fn, _Front..., _Args...>;
359 };
360
361 template <class _Fn, class... _Front>
362 using __mbind_front = __mbind_front_q<_Fn::template __f, _Front...>;
363
364 template <template <class...> class _Fn, class... _Back>
365 struct __mbind_back_q
366 {
367 template <class... _Args>
368 using __f = __meval<_Fn, _Args..., _Back...>;
369 };
370
371 template <class _Fn, class... _Back>
372 using __mbind_back = __mbind_back_q<_Fn::template __f, _Back...>;
373
374 template <template <class...> class _Tp, class... _Args>
375 concept __mvalid = requires { typename __meval<_Tp, _Args...>; };
376
377 template <class _Fn, class... _Args>
378 concept __minvocable = __mvalid<_Fn::template __f, _Args...>;
379
380 template <template <class...> class _Tp, class... _Args>
381 concept __msucceeds = __mvalid<_Tp, _Args...> && __ok<__meval<_Tp, _Args...>>;
382
383 template <class _Fn, class... _Args>
384 concept __minvocable_succeeds = __minvocable<_Fn, _Args...> &&
385 __ok<__minvoke<_Fn, _Args...>>;
386
387 template <class _Fn, class... _Args>
388 struct __force_minvoke_
389 {
390 using __t = __minvoke<_Fn, _Args...>;
391 };
392 template <class _Fn, class... _Args>
393 using __force_minvoke = __t<__force_minvoke_<_Fn, _Args...>>;
394
395 template <class _Fn, class... _Args>
396 struct __mdefer_
397 {};
398
399 template <class _Fn, class... _Args>
400 requires __minvocable<_Fn, _Args...>
401 struct __mdefer_<_Fn, _Args...>
402 {
403 using __t = __minvoke<_Fn, _Args...>;
404 };
405
406 template <class _Fn, class... _Args>
407 struct __mdefer : __mdefer_<_Fn, _Args...>
408 {};
409
410 template <class _Fn, class... _Args>
411 using __mmemoize = __t<__mdefer<_Fn, _Args...>>;
412
413 template <template <class...> class _Fn, class... _Args>
414 using __mmemoize_q = __mmemoize<__q<_Fn>, _Args...>;
415
416 struct __if_
417 {
418 template <bool>
419 struct __
420 {
421 template <class _True, class...>
422 using __f = _True;
423 };
424
425 template <class _Pred, class _True, class... _False>
426 using __f = __minvoke<__<static_cast<bool>(__v<_Pred>)>, _True, _False...>;
427 };
428
429 template <>
430 struct __if_::__<false>
431 {
432 template <class, class _False>
433 using __f = _False;
434 };
435
436 template <class _Pred, class _True = void, class... _False>
437 requires(sizeof...(_False) <= 1)
438 using __if = __minvoke<__if_, _Pred, _True, _False...>;
439
440 template <bool _Pred, class _True = void, class... _False>
441 requires(sizeof...(_False) <= 1)
442 using __if_c = __minvoke<__if_::__<_Pred>, _True, _False...>;
443
444 template <class _Pred, class _True, class _False, class... _Args>
445 using __minvoke_if = __minvoke<__if<_Pred, _True, _False>, _Args...>;
446
447 template <bool _Pred, class _True, class _False, class... _Args>
448 using __minvoke_if_c = __minvoke<__if_c<_Pred, _True, _False>, _Args...>;
449
450 template <class _Tp>
451 struct __mconst
452 {
453 template <class...>
454 using __f = _Tp;
455 };
456
457 inline constexpr __mstring __mbad_substitution =
458 "The specified meta-function could not be evaluated with the types provided."_mstr;
459
460 template <__mstring _Diagnostic = __mbad_substitution>
461 struct _BAD_SUBSTITUTION_
462 {};
463
464 template <class... _Args>
465 struct _WITH_TYPES_;
466
467 template <template <class...> class _Fun>
468 struct _WITH_META_FUNCTION_T_
469 {
470 template <class... _Args>
471 using __f = __mexception<_BAD_SUBSTITUTION_<>, _WITH_META_FUNCTION_T_,
472 _WITH_TYPES_<_Args...>>;
473 };
474
475 template <class _Fun>
476 struct _WITH_META_FUNCTION_
477 {
478 template <class... _Args>
479 using __f = __mexception<_BAD_SUBSTITUTION_<>, _WITH_META_FUNCTION_,
480 _WITH_TYPES_<_Args...>>;
481 };
482
483 template <template <class...> class _Try, class _Catch>
484 struct __mtry_catch_q
485 {
486 template <class... _Args>
487 using __f = __minvoke<__if_c<__mvalid<_Try, _Args...>, __q<_Try>, _Catch>,
488 _Args...>;
489 };
490
491 template <class _Try, class _Catch>
492 struct __mtry_catch
493 {
494 template <class... _Args>
495 using __f =
496 __minvoke<__if_c<__minvocable<_Try, _Args...>, _Try, _Catch>, _Args...>;
497 };
498
499 template <class _Fn, class _Default>
500 using __with_default = __mtry_catch<_Fn, __mconst<_Default>>;
501
502 template <template <class...> class _Fn, class _Default>
503 using __with_default_q = __mtry_catch_q<_Fn, __mconst<_Default>>;
504
505 template <class _Fn, class _Default, class... _Args>
506 using __minvoke_or = __minvoke<__with_default<_Fn, _Default>, _Args...>;
507
508 template <template <class...> class _Fn, class _Default, class... _Args>
509 using __meval_or = __minvoke<__with_default_q<_Fn, _Default>, _Args...>;
510
511 template <template <class...> class _Fn>
512 struct __mtry_eval_
513 {
514 template <class... _Args>
515 using __f = __meval<_Fn, _Args...>;
516 };
517
518 template <template <class...> class _Fn, class... _Args>
519 using __mtry_eval =
520 __minvoke<__mtry_catch<__mtry_eval_<_Fn>, _WITH_META_FUNCTION_T_<_Fn>>,
521 _Args...>;
522
523 template <class _Fn, class... _Args>
524 using __mtry_invoke =
525 __minvoke<__mtry_catch<_Fn, _WITH_META_FUNCTION_<_Fn>>, _Args...>;
526
527 template <class _Ty, class... _Default>
528 using __msuccess_or_t = __if_c<__ok<_Ty>, _Ty, _Default...>;
529
530 template <class _Fn, class _Continuation = __q<__types>>
531 struct __transform
532 {
533 template <class... _Args>
534 using __f = __minvoke<_Continuation, __minvoke<_Fn, _Args>...>;
535 };
536
537 template <bool>
538 struct __mfold_right_
539 {
540 template <class _Fn, class _State, class _Head, class... _Tail>
541 using __f = __minvoke<__mfold_right_<sizeof...(_Tail) == 0>, _Fn,
542 __minvoke<_Fn, _State, _Head>, _Tail...>;
543 };
544
545 template <>
546 struct __mfold_right_<true>
547 { // empty pack
548 template <class _Fn, class _State, class...>
549 using __f = _State;
550 };
551
552 template <class _Init, class _Fn>
553 struct __mfold_right
554 {
555 template <class... _Args>
556 using __f =
557 __minvoke<__mfold_right_<sizeof...(_Args) == 0>, _Fn, _Init, _Args...>;
558 };
559
560 template <class _Continuation, class... _As>
561 struct __mconcat_
562 {};
563
564 template <class _Continuation, class... _As>
565 requires(sizeof...(_As) == 0) && __minvocable<_Continuation, _As...>
566 struct __mconcat_<_Continuation, _As...>
567 {
568 using __t = __minvoke<_Continuation, _As...>;
569 };
570
571 template <class _Continuation, template <class...> class _Ap, class... _As>
572 requires __minvocable<_Continuation, _As...>
573 struct __mconcat_<_Continuation, _Ap<_As...>>
574 {
575 using __t = __minvoke<_Continuation, _As...>;
576 };
577
578 template < //
579 class _Continuation, //
580 template <class...> class _Ap,
581 class... _As, //
582 template <class...> class _Bp, class... _Bs>
583 requires __minvocable<_Continuation, _As..., _Bs...>
584 struct __mconcat_<_Continuation, _Ap<_As...>, _Bp<_Bs...>>
585 {
586 using __t = __minvoke<_Continuation, _As..., _Bs...>;
587 };
588
589 template < //
590 class _Continuation, //
591 template <class...> class _Ap,
592 class... _As, //
593 template <class...> class _Bp,
594 class... _Bs, //
595 template <class...> class _Cp, class... _Cs>
596 requires __minvocable<_Continuation, _As..., _Bs..., _Cs...>
597 struct __mconcat_<_Continuation, _Ap<_As...>, _Bp<_Bs...>, _Cp<_Cs...>>
598 {
599 using __t = __minvoke<_Continuation, _As..., _Bs..., _Cs...>;
600 };
601
602 template < //
603 class _Continuation, //
604 template <class...> class _Ap,
605 class... _As, //
606 template <class...> class _Bp,
607 class... _Bs, //
608 template <class...> class _Cp,
609 class... _Cs, //
610 template <class...> class _Dp,
611 class... _Ds, //
612 class... _Tail>
613 struct __mconcat_<_Continuation, _Ap<_As...>, _Bp<_Bs...>, _Cp<_Cs...>,
614 _Dp<_Ds...>, _Tail...> :
615 __mconcat_<_Continuation, __types<_As..., _Bs..., _Cs..., _Ds...>, _Tail...>
616 {};
617
618 template <class _Continuation = __q<__types>>
619 struct __mconcat
620 {
621 template <class... _Args>
622 using __f = __t<__mconcat_<_Continuation, _Args...>>;
623 };
624
625 template <class _Fn>
626 struct __curry
627 {
628 template <class... _Ts>
629 using __f = __minvoke<_Fn, _Ts...>;
630 };
631
632 template <class _Fn, class _Tp>
633 struct __uncurry_;
634
635 template <__merror _Fn, class _Tp>
636 struct __uncurry_<_Fn, _Tp>
637 {
638 using __t = _Fn;
639 };
640
641 template <class _Fn, template <class...> class _Ap, class... _As>
642 requires __minvocable<_Fn, _As...>
643 struct __uncurry_<_Fn, _Ap<_As...>>
644 {
645 using __t = __minvoke<_Fn, _As...>;
646 };
647
648 template <class _Fn>
649 struct __uncurry
650 {
651 template <class _Tp>
652 using __f = __t<__uncurry_<_Fn, _Tp>>;
653 };
654 template <class _Fn, class _List>
655 using __mapply = __minvoke<__uncurry<_Fn>, _List>;
656
657 struct __msize
658 {
659 template <class... _Ts>
660 using __f = __msize_t<sizeof...(_Ts)>;
661 };
662
663 template <class _Ty>
664 struct __mcount
665 {
666 template <class... _Ts>
667 using __f = __msize_t<(__same_as<_Ts, _Ty> + ... + 0)>;
668 };
669
670 template <class _Fn>
671 struct __mcount_if
672 {
673 template <class... _Ts>
674 using __f = __msize_t<(bool(__v<__minvoke<_Fn, _Ts>>) + ... + 0)>;
675 };
676
677 template <class _Tp>
678 struct __contains
679 {
680 template <class... _Args>
681 using __f = __mbool<(__same_as<_Tp, _Args> || ...)>;
682 };
683
684 template <class _Continuation = __q<__types>>
685 struct __push_back
686 {
687 template <class _List, class _Item>
688 using __f = __mapply<__mbind_back<_Continuation, _Item>, _List>;
689 };
690
691 template <class _Continuation = __q<__types>>
692 struct __push_back_unique
693 {
694 template <class _List, class _Item>
695 using __f = //
696 __mapply<__if<__mapply<__contains<_Item>, _List>, _Continuation,
697 __mbind_back<_Continuation, _Item>>,
698 _List>;
699 };
700
701 template <class _Continuation = __q<__types>>
702 struct __munique
703 {
704 template <class... _Ts>
705 using __f = __mapply<
706 _Continuation,
707 __minvoke<__mfold_right<__types<>, __push_back_unique<>>, _Ts...>>;
708 };
709
710 template <class...>
711 struct __mcompose
712 {};
713
714 template <class _First>
715 struct __mcompose<_First> : _First
716 {};
717
718 template <class _Second, class _First>
719 struct __mcompose<_Second, _First>
720 {
721 template <class... _Args>
722 using __f = __minvoke<_Second, __minvoke<_First, _Args...>>;
723 };
724
725 template <class _Last, class _Penultimate, class... _Rest>
726 struct __mcompose<_Last, _Penultimate, _Rest...>
727 {
728 template <class... _Args>
729 using __f =
730 __minvoke<_Last,
731 __minvoke<__mcompose<_Penultimate, _Rest...>, _Args...>>;
732 };
733
734 template <class _Old, class _New, class _Continuation = __q<__types>>
735 struct __replace
736 {
737 template <class... _Args>
738 using __f = __minvoke<_Continuation,
739 __if_c<__same_as<_Args, _Old>, _New, _Args>...>;
740 };
741
742 template <class _Old, class _Continuation = __q<__types>>
743 struct __remove
744 {
745 template <class... _Args>
746 using __f = //
747 __minvoke<__mconcat<_Continuation>,
748 __if_c<__same_as<_Args, _Old>, __types<>, __types<_Args>>...>;
749 };
750
751 template <class _Pred, class _Continuation = __q<__types>>
752 struct __remove_if
753 {
754 template <class... _Args>
755 using __f = //
756 __minvoke<__mconcat<_Continuation>,
757 __if<__minvoke<_Pred, _Args>, __types<>, __types<_Args>>...>;
758 };
759
760 template <class _Return>
761 struct __qf
762 {
763 template <class... _Args>
764 using __f = _Return(_Args...);
765 };
766
767 template <class _Ty, class...>
768 using __mfront_ = _Ty;
769 template <class... _As>
770 using __mfront = __meval<__mfront_, _As...>;
771 template <class... _As>
772 requires(sizeof...(_As) == 1)
773 using __msingle = __mfront<_As...>;
774 template <class _Default, class... _As>
775 requires(sizeof...(_As) <= 1)
776 using __msingle_or_ = __mfront<_As..., _Default>;
777 template <class _Default>
778 using __msingle_or = __mbind_front_q<__msingle_or_, _Default>;
779
780 template <class _Continuation = __q<__types>>
781 struct __pop_front
782 {
783 template <class, class... _Ts>
784 using __f = __minvoke<_Continuation, _Ts...>;
785 };
786
787 template <class _Ty>
788 concept __has_id = requires { typename _Ty::__id; };
789
790 template <class _Ty>
791 struct _Id
792 {
793 using __t = _Ty;
794
795 // Uncomment the line below to find any code that likely misuses the
796 // ADL isolation mechanism. In particular, '__id<T>' when T is a
797 // reference is a likely misuse. The static_assert below will trigger
798 // when the type passed to the __id alias template is a reference to
799 // a type that is setup to use ADL isolation.
800 // static_assert(!__has_id<std::remove_cvref_t<_Ty>>);
801 };
802
803 template <bool = true>
804 struct __id_
805 {
806 template <class _Ty>
807 using __f = typename _Ty::__id;
808 };
809
810 template <>
811 struct __id_<false>
812 {
813 template <class _Ty>
814 using __f = _Id<_Ty>;
815 };
816 template <class _Ty>
817 using __id = __minvoke<__id_<__has_id<_Ty>>, _Ty>;
818
819 template <class _From, class _To = __decay_t<_From>>
820 using __cvref_t = __copy_cvref_t<_From, __t<_To>>;
821
822 template <class _From, class _To = __decay_t<_From>>
823 using __cvref_id = __copy_cvref_t<_From, __id<_To>>;
824
825 #if STDEXEC_NVHPC()
826 // nvc++ doesn't cache the results of alias template specializations.
827 // To avoid repeated computation of the same function return type,
828 // cache the result ourselves in a class template specialization.
829 template <class _Fun, class... _As>
830 using __call_result_ = decltype(__declval<_Fun>()(__declval<_As>()...));
831 template <class _Fun, class... _As>
832 using __call_result_t = __t<__mdefer<__q<__call_result_>, _Fun, _As...>>;
833 #else
834 template <class _Fun, class... _As>
835 using __call_result_t = decltype(__declval<_Fun>()(__declval<_As>()...));
836 #endif
837
838 template <const auto& _Fun, class... _As>
839 using __result_of = __call_result_t<decltype(_Fun), _As...>;
840
841 // For working around clang's lack of support for CWG#2369:
842 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2369
843 struct __qcall_result
844 {
845 template <class _Fun, class... _As>
846 using __f = __call_result_t<_Fun, _As...>;
847 };
848 template <bool _Enable, class _Fun, class... _As>
849 using __call_result_if_t =
850 __minvoke<__if<__mbool<_Enable>, __qcall_result, __>, _Fun, _As...>;
851
852 // For emplacing non-movable types into optionals:
853 template <class _Fn>
854 requires std::is_nothrow_move_constructible_v<_Fn>
855 struct __conv
856 {
857 _Fn __fn_;
858 using __t = __call_result_t<_Fn>;
859
operator __tstdexec::__conv860 operator __t() && noexcept(__nothrow_callable<_Fn>)
861 {
862 return static_cast<_Fn&&>(__fn_)();
863 }
864
operator ()stdexec::__conv865 auto operator()() && noexcept(__nothrow_callable<_Fn>) -> __t
866 {
867 return static_cast<_Fn&&>(__fn_)();
868 }
869 };
870 template <class _Fn>
871 __conv(_Fn) -> __conv<_Fn>;
872
873 // Implemented as a class instead of a free function
874 // because of a bizarre nvc++ compiler bug:
875 struct __cref_fn
876 {
877 template <class _Ty>
878 auto operator()(const _Ty&) -> const _Ty&;
879 };
880 template <class _Ty>
881 using __cref_t = decltype(__cref_fn{}(__declval<_Ty>()));
882
883 template <class, class, class, class>
884 struct __mzip_with2_;
885
886 template < //
887 class _Fn, //
888 class _Continuation, //
889 template <class...> class _Cp,
890 class... _Cs, //
891 template <class...> class _Dp, class... _Ds>
892 requires requires {
893 typename __minvoke<_Continuation, __minvoke<_Fn, _Cs, _Ds>...>;
894 }
895 struct __mzip_with2_<_Fn, _Continuation, _Cp<_Cs...>, _Dp<_Ds...>>
896 {
897 using __t = __minvoke<_Continuation, __minvoke<_Fn, _Cs, _Ds>...>;
898 };
899
900 template <class _Fn, class _Continuation = __q<__types>>
901 struct __mzip_with2
902 {
903 template <class _Cp, class _Dp>
904 using __f = __t<__mzip_with2_<_Fn, _Continuation, _Cp, _Dp>>;
905 };
906
907 #if STDEXEC_GCC() && (__GNUC__ < 12)
908 template <class>
909 extern int __mconvert_indices;
910 template <std::size_t... _Indices>
911 extern __types<__msize_t<_Indices>...>
912 __mconvert_indices<std::index_sequence<_Indices...>>;
913 template <std::size_t _Np>
914 using __mmake_index_sequence =
915 decltype(stdexec::__mconvert_indices<std::make_index_sequence<_Np>>);
916 #else
917 template <std::size_t... _Indices>
918 auto __mconvert_indices(std::index_sequence<_Indices...>*)
919 -> __types<__msize_t<_Indices>...>;
920 template <std::size_t _Np>
921 using __mmake_index_sequence = decltype(stdexec::__mconvert_indices(
922 static_cast<std::make_index_sequence<_Np>*>(nullptr)));
923 #endif
924
925 template <class... _Ts>
926 using __mindex_sequence_for = __mmake_index_sequence<sizeof...(_Ts)>;
927
928 template <bool>
929 struct __mfind_if_
930 {
931 template <class _Fn, class _Continuation, class _Head, class... _Tail>
932 using __f = //
933 __minvoke<__if_c<__v<__minvoke<_Fn, _Head>>,
934 __mbind_front<_Continuation, _Head>,
935 __mbind_front<__mfind_if_<(sizeof...(_Tail) != 0)>,
936 _Fn, _Continuation>>,
937 _Tail...>;
938 };
939
940 template <>
941 struct __mfind_if_<false>
942 {
943 template <class _Fn, class _Continuation>
944 using __f = __minvoke<_Continuation>;
945 };
946
947 template <class _Fn, class _Continuation = __q<__types>>
948 struct __mfind_if
949 {
950 template <class... _Args>
951 using __f = __minvoke<__mfind_if_<(sizeof...(_Args) != 0)>, _Fn,
952 _Continuation, _Args...>;
953 };
954
955 template <class _Fn>
956 struct __mfind_if_i
957 {
958 template <class... _Args>
959 using __f = __msize_t<(sizeof...(_Args) -
960 __v<__minvoke<__mfind_if<_Fn, __msize>, _Args...>>)>;
961 };
962
963 template <class... _Booleans>
964 using __mand_ = __mbool<(__v<_Booleans> && ...)>;
965 template <class... _Booleans>
966 using __mand = __meval<__mand_, _Booleans...>;
967
968 template <class... _Booleans>
969 using __mor_ = __mbool<(__v<_Booleans> || ...)>;
970 template <class... _Booleans>
971 using __mor = __meval<__mor_, _Booleans...>;
972
973 template <class _Boolean>
974 using __mnot_ = __mbool<!__v<_Boolean>>;
975 template <class _Boolean>
976 using __mnot = __meval<__mnot_, _Boolean>;
977
978 template <class _Fn>
979 struct __mall_of
980 {
981 template <class... _Args>
982 using __f = __mand<__minvoke<_Fn, _Args>...>;
983 };
984
985 template <class _Fn>
986 struct __mnone_of
987 {
988 template <class... _Args>
989 using __f = __mand<__mnot<__minvoke<_Fn, _Args>>...>;
990 };
991
992 template <class _Fn>
993 struct __many_of
994 {
995 template <class... _Args>
996 using __f = __mor<__minvoke<_Fn, _Args>...>;
997 };
998
999 #if STDEXEC_HAS_BUILTIN(__type_pack_element)
1000 template <std::size_t _Np, class... _Ts>
1001 struct __m_at_
1002 {
1003 using __t = __type_pack_element<_Np, _Ts...>;
1004 };
1005
1006 template <std::size_t _Np, class... _Ts>
1007 using __m_at_c = __t<__m_at_<_Np, _Ts...>>;
1008 #else
1009 template <std::size_t>
1010 using __void_ptr = void*;
1011
1012 template <class _Ty>
1013 using __mtype_ptr = __mtype<_Ty>*;
1014
1015 template <class _Ty>
1016 struct __m_at_;
1017
1018 template <std::size_t... _Is>
1019 struct __m_at_<std::index_sequence<_Is...>>
1020 {
1021 template <class _Up, class... _Us>
1022 static _Up __f_(__void_ptr<_Is>..., _Up*, _Us*...);
1023 template <class... _Ts>
1024 using __f = __t<decltype(__m_at_::__f_(__mtype_ptr<_Ts>()...))>;
1025 };
1026
1027 template <std::size_t _Np, class... _Ts>
1028 using __m_at_c = __minvoke<__m_at_<std::make_index_sequence<_Np>>, _Ts...>;
1029 #endif
1030
1031 template <class _Np, class... _Ts>
1032 using __m_at = __m_at_c<__v<_Np>, _Ts...>;
1033
1034 template <class... _Ts>
1035 using __mback = __m_at_c<sizeof...(_Ts) - 1, _Ts...>;
1036
1037 template <class _Continuation = __q<__types>>
1038 struct __mpop_back
1039 {
1040 template <class>
1041 struct __impl;
1042
1043 template <std::size_t... _Idx>
1044 struct __impl<__indices<_Idx...>>
1045 {
1046 template <class... _Ts>
1047 using __f = __minvoke<_Continuation, __m_at_c<_Idx, _Ts...>...>;
1048 };
1049
1050 template <class... _Ts>
1051 requires(sizeof...(_Ts) != 0)
1052 using __f = __minvoke<__impl<__make_indices<sizeof...(_Ts) - 1>>, _Ts...>;
1053 };
1054
1055 template <std::size_t _Np>
1056 struct __placeholder
1057 {
1058 __placeholder() = default;
1059
__placeholderstdexec::__placeholder1060 constexpr __placeholder(void*) noexcept {}
1061
__get_placeholder_offset(__placeholder)1062 friend constexpr auto __get_placeholder_offset(__placeholder) noexcept
1063 -> std::size_t
1064 {
1065 return _Np;
1066 }
1067 };
1068
1069 using __0 = __placeholder<0>;
1070 using __1 = __placeholder<1>;
1071 using __2 = __placeholder<2>;
1072 using __3 = __placeholder<3>;
1073
1074 #if STDEXEC_MSVC()
1075 // MSVCBUG
1076 // https://developercommunity.visualstudio.com/t/Incorrect-function-template-argument-sub/10437827
1077
1078 template <std::size_t>
1079 struct __ignore_t
1080 {
1081 __ignore_t() = default;
1082
__ignore_tstdexec::__ignore_t1083 constexpr __ignore_t(auto&&...) noexcept {}
1084 };
1085 #else
1086 template <std::size_t>
1087 using __ignore_t = __ignore;
1088 #endif
1089
1090 template <class... _Ignore>
1091 struct __nth_pack_element_impl
1092 {
1093 template <class _Ty, class... _Us>
1094 STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_pack_element_impl1095 constexpr _Ty&& operator()(_Ignore..., _Ty&& __t, _Us&&...) const noexcept
1096 {
1097 return static_cast<decltype(__t)&&>(__t);
1098 }
1099 };
1100
1101 template <std::size_t _Np>
1102 struct __nth_pack_element_t
1103 {
1104 template <std::size_t... _Is>
1105 STDEXEC_ATTRIBUTE((always_inline))
__implstdexec::__nth_pack_element_t1106 static constexpr auto __impl(__indices<_Is...>) noexcept
1107 {
1108 return __nth_pack_element_impl<__ignore_t<_Is>...>();
1109 }
1110
1111 template <class... _Ts>
1112 STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_pack_element_t1113 constexpr decltype(auto) operator()(_Ts&&... __ts) const noexcept
1114 {
1115 static_assert(_Np < sizeof...(_Ts));
1116 return __impl(__make_indices<_Np>())(static_cast<_Ts&&>(__ts)...);
1117 }
1118 };
1119
1120 template <std::size_t _Np>
1121 inline constexpr __nth_pack_element_t<_Np> __nth_pack_element{};
1122
1123 template <auto... _Vs>
1124 struct __mliterals
1125 {
1126 template <std::size_t _Np>
1127 STDEXEC_ATTRIBUTE((always_inline))
__nthstdexec::__mliterals1128 static constexpr auto __nth() noexcept
1129 {
1130 return stdexec::__nth_pack_element<_Np>(_Vs...);
1131 }
1132 };
1133
1134 template <std::size_t _Np>
1135 struct __nth_member
1136 {
1137 template <class _Ty>
1138 STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__nth_member1139 constexpr decltype(auto) operator()(_Ty&& __ty) const noexcept
1140 {
1141 return static_cast<_Ty&&>(__ty).*(__ty.__mbrs_.template __nth<_Np>());
1142 }
1143 };
1144
1145 template <class _Ty, std::size_t _Offset = 0>
1146 struct __mdispatch_
1147 {
1148 template <class... _Ts>
operator ()stdexec::__mdispatch_1149 auto operator()(_Ts&&...) const noexcept(noexcept(_Ty{})) -> _Ty
1150 {
1151 return _Ty{};
1152 }
1153 };
1154
1155 template <std::size_t _Np, std::size_t _Offset>
1156 struct __mdispatch_<__placeholder<_Np>, _Offset>
1157 {
1158 template <class... _Ts>
operator ()stdexec::__mdispatch_1159 auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1160 {
1161 return stdexec::__nth_pack_element<_Np + _Offset>(
1162 static_cast<_Ts&&>(__ts)...);
1163 }
1164 };
1165
1166 template <std::size_t _Np, std::size_t _Offset>
1167 struct __mdispatch_<__placeholder<_Np>&, _Offset>
1168 {
1169 template <class... _Ts>
operator ()stdexec::__mdispatch_1170 auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1171 {
1172 return stdexec::__nth_pack_element<_Np + _Offset>(__ts...);
1173 }
1174 };
1175
1176 template <std::size_t _Np, std::size_t _Offset>
1177 struct __mdispatch_<__placeholder<_Np>&&, _Offset>
1178 {
1179 template <class... _Ts>
operator ()stdexec::__mdispatch_1180 auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1181 {
1182 return std::move(stdexec::__nth_pack_element<_Np + _Offset>(__ts...));
1183 }
1184 };
1185
1186 template <std::size_t _Np, std::size_t _Offset>
1187 struct __mdispatch_<const __placeholder<_Np>&, _Offset>
1188 {
1189 template <class... _Ts>
operator ()stdexec::__mdispatch_1190 auto operator()(_Ts&&... __ts) const noexcept -> decltype(auto)
1191 {
1192 return std::as_const(
1193 stdexec::__nth_pack_element<_Np + _Offset>(__ts...));
1194 }
1195 };
1196
1197 template <class _Ret, class... _Args, std::size_t _Offset>
1198 struct __mdispatch_<_Ret (*)(_Args...), _Offset>
1199 {
1200 template <class... _Ts>
1201 requires(__callable<__mdispatch_<_Args, _Offset>, _Ts...> && ...) &&
1202 __callable<_Ret, __call_result_t<__mdispatch_<_Args, _Offset>,
1203 _Ts...>...>
operator ()stdexec::__mdispatch_1204 auto operator()(_Ts&&... __ts) const noexcept(
1205 __nothrow_callable<
1206 _Ret, __call_result_t<__mdispatch_<_Args, _Offset>, _Ts...>...>)
1207 -> __call_result_t<
1208 _Ret, __call_result_t<__mdispatch_<_Args, _Offset>, _Ts...>...>
1209 {
1210 return _Ret{}(
1211 __mdispatch_<_Args, _Offset>{}(static_cast<_Ts&&>(__ts)...)...);
1212 }
1213 };
1214
1215 template <class _Ret, class... _Args, std::size_t _Offset>
1216 struct __mdispatch_<_Ret (*)(_Args..., ...), _Offset>
1217 {
1218 static_assert(_Offset == 0, "nested pack expressions are not supported");
1219 using _Pattern = __mback<_Args...>;
1220 static constexpr std::size_t __offset =
1221 __get_placeholder_offset(static_cast<__mtype<_Pattern>*>(nullptr));
1222
1223 struct __impl
1224 {
1225 template <std::size_t... _Idx, class... _Ts>
1226 requires(__callable<__mdispatch_<_Args>, _Ts...> && ...) &&
1227 (__callable<__mdispatch_<_Pattern, _Idx + 1>, _Ts...> &&
1228 ...) &&
1229 __callable< //
1230 _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...,
1231 __call_result_t<__mdispatch_<_Pattern, _Idx + 1>,
1232 _Ts...>...>
operator ()stdexec::__mdispatch_::__impl1233 auto operator()(__indices<_Idx...>, _Ts&&... __ts) const noexcept(
1234 __nothrow_callable< //
1235 _Ret, //
1236 __call_result_t<__mdispatch_<_Args>, _Ts...>..., //
1237 __call_result_t<__mdispatch_<_Pattern, _Idx + 1>, _Ts...>...>)
1238 -> __call_result_t< //
1239 _Ret, __call_result_t<__mdispatch_<_Args>, _Ts...>...,
1240 __call_result_t<__mdispatch_<_Pattern, _Idx + 1>, _Ts...>...>
1241 {
1242 return _Ret()( //
1243 __mdispatch_<_Args>()(static_cast<_Ts&&>(__ts)...)..., //
1244 __mdispatch_<_Pattern, _Idx + 1>()(
1245 static_cast<_Ts&&>(__ts)...)...);
1246 }
1247 };
1248
1249 template <class... _Ts>
1250 requires(__offset < sizeof...(_Ts)) &&
1251 __callable<__impl,
1252 __make_indices<sizeof...(_Ts) - __offset - 1>,
1253 _Ts...>
operator ()stdexec::__mdispatch_1254 auto operator()(_Ts&&... __ts) const noexcept(
1255 __nothrow_callable<
1256 __impl, __make_indices<sizeof...(_Ts) - __offset - 1>, _Ts...>)
1257 -> __msecond<
1258 __if_c<(__offset < sizeof...(_Ts))>,
1259 __call_result_t<
1260 __impl, __make_indices<sizeof...(_Ts) - __offset - 1>, _Ts...>>
1261 {
1262 return __impl()(__make_indices<sizeof...(_Ts) - __offset - 1>(),
1263 static_cast<_Ts&&>(__ts)...);
1264 }
1265
1266 template <class... _Ts>
1267 requires(sizeof...(_Ts) == __offset) &&
1268 __callable<
1269 __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>,
1270 _Ts...>
operator ()stdexec::__mdispatch_1271 auto operator()(_Ts&&... __ts) const
1272 noexcept(__nothrow_callable<
1273 __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>,
1274 _Ts...>)
1275 -> __msecond<
1276 __if_c<(sizeof...(_Ts) == __offset)>,
1277 __call_result_t<
1278 __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>,
1279 _Ts...>>
1280 {
1281 return __mdispatch_<__minvoke<__mpop_back<__qf<_Ret>>, _Args...>*>()(
1282 static_cast<_Ts&&>(__ts)...);
1283 }
1284 };
1285
1286 template <class _Ty>
1287 struct __mdispatch
1288 {};
1289
1290 template <class _Ret, class... _Args>
1291 struct __mdispatch<_Ret(_Args...)> : __mdispatch_<_Ret (*)(_Args...)>
1292 {};
1293
1294 template <class _Ret, class... _Args>
1295 struct __mdispatch<_Ret(_Args..., ...)> : __mdispatch_<_Ret (*)(_Args..., ...)>
1296 {};
1297
1298 template <class _Ty, class... _Ts>
1299 concept __dispatchable = __callable<__mdispatch<_Ty>, _Ts...>;
1300
1301 template <class _Ty, class... _Ts>
1302 concept __nothrow_dispatchable = __nothrow_callable<__mdispatch<_Ty>, _Ts...>;
1303
1304 template <class _Ty, class... _Ts>
1305 using __dispatch_result_t = __call_result_t<__mdispatch<_Ty>, _Ts...>;
1306
1307 template <class _Signature, class... _Args>
1308 using __try_dispatch_ = __mbool<__dispatchable<_Signature, _Args...>>;
1309
1310 template <class _Signatures, class _Continuation = __q<__mfront>>
1311 struct __which
1312 {};
1313
1314 template <template <class...> class _Cp, class... _Signatures,
1315 class _Continuation>
1316 struct __which<_Cp<_Signatures...>, _Continuation>
1317 {
1318 template <class... _Args>
1319 using __f = //
1320 __minvoke<__mfind_if<__mbind_back_q<__try_dispatch_, _Args...>,
1321 _Continuation>,
1322 _Signatures...>;
1323 };
1324
1325 template <class _Signatures, class _DefaultFn, class... _Args>
1326 using __make_dispatcher = //
1327 __minvoke<__mtry_catch<__mcompose<__q<__mdispatch>, __which<_Signatures>>,
1328 _DefaultFn>,
1329 _Args...>;
1330 } // namespace stdexec
1331