1 /* 2 * Copyright (c) 2023 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 "__config.hpp" 19 #include "__type_traits.hpp" 20 21 #if 0 // STDEXEC_HAS_STD_RANGES() 22 23 #include <ranges> 24 25 namespace stdexec::ranges { 26 using std::ranges::begin; 27 using std::ranges::end; 28 29 using std::ranges::range_value_t; 30 using std::ranges::range_reference_t; 31 using std::ranges::iterator_t; 32 using std::ranges::sentinel_t; 33 } 34 35 #else 36 37 #include <iterator> 38 39 namespace stdexec::ranges 40 { 41 42 namespace __detail 43 { 44 void begin(); 45 void end(); 46 47 template <class _Ty> 48 concept __has_member_begin = 49 requires(_Ty&& __v) { static_cast<_Ty&&>(__v).begin(); }; 50 51 template <class _Ty> 52 concept __has_free_begin = 53 __has_member_begin<_Ty> || 54 requires(_Ty&& __v) { begin((static_cast<_Ty&&>(__v))); }; 55 56 template <class _Ty> 57 concept __has_member_end = 58 requires(_Ty&& __v) { static_cast<_Ty&&>(__v).end(); }; 59 60 template <class _Ty> 61 concept __has_free_end = 62 __has_member_end<_Ty> || 63 requires(_Ty&& __v) { end((static_cast<_Ty&&>(__v))); }; 64 65 struct __begin_t 66 { 67 template <class _Range> 68 requires __has_member_begin<_Range> operator ()stdexec::ranges::__detail::__begin_t69 auto operator()(_Range&& __rng) const 70 noexcept(noexcept((static_cast<_Range&&>(__rng)).begin())) 71 -> decltype((static_cast<_Range&&>(__rng)).begin()) 72 { 73 return static_cast<_Range&&>(__rng).begin(); 74 } 75 76 template <class _Range> 77 requires __has_free_begin<_Range> operator ()stdexec::ranges::__detail::__begin_t78 auto operator()(_Range&& __rng) const 79 noexcept(noexcept(begin((static_cast<_Range&&>(__rng))))) 80 -> decltype(begin((static_cast<_Range&&>(__rng)))) 81 { 82 return begin((static_cast<_Range&&>(__rng))); 83 } 84 }; 85 86 struct __end_t 87 { 88 template <class _Range> 89 requires __has_member_end<_Range> operator ()stdexec::ranges::__detail::__end_t90 auto operator()(_Range&& __rng) const 91 noexcept(noexcept((static_cast<_Range&&>(__rng)).end())) 92 -> decltype((static_cast<_Range&&>(__rng)).end()) 93 { 94 return static_cast<_Range&&>(__rng).end(); 95 } 96 97 template <class _Range> 98 requires __has_free_end<_Range> operator ()stdexec::ranges::__detail::__end_t99 auto operator()(_Range&& __rng) const 100 noexcept(noexcept(end((static_cast<_Range&&>(__rng))))) 101 -> decltype(end((static_cast<_Range&&>(__rng)))) 102 { 103 return end((static_cast<_Range&&>(__rng))); 104 } 105 }; 106 } // namespace __detail 107 108 inline constexpr __detail::__begin_t begin{}; 109 inline constexpr __detail::__end_t end{}; 110 111 template <class _Range> 112 using iterator_t = decltype(begin((__declval<_Range>()))); 113 114 template <class _Range> 115 using sentinel_t = decltype(end((__declval<_Range>()))); 116 117 template <class _Range> 118 using range_reference_t = decltype(*begin((__declval<_Range>()))); 119 120 template <class _Range> 121 using range_value_t = 122 typename std::iterator_traits<iterator_t<_Range>>::value_type; 123 124 } // namespace stdexec::ranges 125 126 #endif 127