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