xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/__ranges/access.h (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1 // -*- C++ -*-
2 //===------------------------ __ranges/access.h ---------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___RANGES_ACCESS_H
10 #define _LIBCPP___RANGES_ACCESS_H
11 
12 #include <__config>
13 #include <__iterator/concepts.h>
14 #include <__ranges/enable_borrowed_range.h>
15 #include <type_traits>
16 
17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18 #pragma GCC system_header
19 #endif
20 
21 _LIBCPP_PUSH_MACROS
22 #include <__undef_macros>
23 
24 _LIBCPP_BEGIN_NAMESPACE_STD
25 
26 #if !defined(_LIBCPP_HAS_NO_RANGES)
27 
28 // clang-format off
29 
30 namespace ranges {
31   template <class _Tp>
32   concept __can_borrow =
33       is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp> >;
34 
35   template<class _Tp>
36   concept __is_complete = requires { sizeof(_Tp); };
37 } // namespace ranges
38 
39 // [range.access.begin]
40 namespace ranges::__begin {
41   template <class _Tp>
42   concept __member_begin =
43     __can_borrow<_Tp> &&
requires(_Tp && __t)44     requires(_Tp&& __t) {
45       { _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator;
46     };
47 
48   void begin(auto&) = delete;
49   void begin(const auto&) = delete;
50 
51   template <class _Tp>
52   concept __unqualified_begin =
53     !__member_begin<_Tp> &&
54     __can_borrow<_Tp> &&
55     __class_or_enum<remove_cvref_t<_Tp> > &&
56     requires(_Tp && __t) {
57       { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator;
58     };
59 
60   struct __fn {
61     template <class _Tp>
62     requires is_array_v<remove_cv_t<_Tp>>
operator__fn63     [[nodiscard]] constexpr auto operator()(_Tp& __t) const noexcept {
64       constexpr bool __complete = __is_complete<iter_value_t<_Tp> >;
65       if constexpr (__complete) { // used to disable cryptic diagnostic
66         return __t + 0;
67       }
68       else {
69         static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type.");
70       }
71     }
72 
73     template <class _Tp>
74     requires __member_begin<_Tp>
operator__fn75     [[nodiscard]] constexpr auto operator()(_Tp&& __t) const
76     noexcept(noexcept(_VSTD::__decay_copy(__t.begin())))
77     {
78       return __t.begin();
79     }
80 
81     template <class _Tp>
82     requires __unqualified_begin<_Tp>
operator__fn83     [[nodiscard]] constexpr auto operator()(_Tp&& __t) const
84     noexcept(noexcept(_VSTD::__decay_copy(begin(__t))))
85     {
86       return begin(__t);
87     }
88 
89     void operator()(auto&&) const = delete;
90   };
91 } // namespace ranges::__begin
92 
93 namespace ranges {
94   inline namespace __cpo {
95     inline constexpr auto begin = __begin::__fn{};
96   } // namespace __cpo
97 
98   template <class _Tp>
99   using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
100 } // namespace ranges
101 
102 // [range.access.end]
103 namespace ranges::__end {
104   template <class _Tp>
105   concept __member_end =
106     __can_borrow<_Tp> &&
requires(_Tp && __t)107     requires(_Tp&& __t) {
108       typename iterator_t<_Tp>;
109       { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >;
110     };
111 
112   void end(auto&) = delete;
113   void end(const auto&) = delete;
114 
115   template <class _Tp>
116   concept __unqualified_end =
117     !__member_end<_Tp> &&
118     __can_borrow<_Tp> &&
119     __class_or_enum<remove_cvref_t<_Tp> > &&
120     requires(_Tp && __t) {
121       typename iterator_t<_Tp>;
122       { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >;
123     };
124 
125   class __fn {
126   public:
127     template <class _Tp, size_t _Np>
operator()128     [[nodiscard]] constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept {
129       constexpr bool __complete = __is_complete<remove_cv_t<_Tp> >;
130       if constexpr (__complete) { // used to disable cryptic diagnostic
131         return __t + _Np;
132       }
133       else {
134         static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type.");
135       }
136     }
137 
138     template <class _Tp>
139     requires __member_end<_Tp>
operator()140     [[nodiscard]] constexpr auto operator()(_Tp&& __t) const
141     noexcept(noexcept(_VSTD::__decay_copy(__t.end())))
142     {
143       return _VSTD::forward<_Tp>(__t).end();
144     }
145 
146     template <class _Tp>
147     requires __unqualified_end<_Tp>
operator()148     [[nodiscard]] constexpr auto operator()(_Tp&& __t) const
149     noexcept(noexcept(_VSTD::__decay_copy(end(__t))))
150     {
151       return end(__t);
152     }
153 
154     void operator()(auto&&) const = delete;
155   };
156 } // namespace ranges::__end
157 
158 namespace ranges::inline __cpo {
159   inline constexpr auto end = __end::__fn{};
160 } // namespace ranges::__cpo
161 
162 namespace ranges::__cbegin {
163   struct __fn {
164     template <class _Tp>
165     requires invocable<decltype(ranges::begin), _Tp const&>
operator__fn166     [[nodiscard]] constexpr auto operator()(_Tp& __t) const
167     noexcept(noexcept(ranges::begin(_VSTD::as_const(__t))))
168     {
169       return ranges::begin(_VSTD::as_const(__t));
170     }
171 
172     template <class _Tp>
173     requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::begin), _Tp const&&>
operator__fn174     [[nodiscard]] constexpr auto operator()(_Tp&& __t) const
175     noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t))))
176     {
177       return ranges::begin(static_cast<_Tp const&&>(__t));
178     }
179   };
180 } // namespace ranges::__cbegin
181 
182 namespace ranges::inline __cpo {
183   inline constexpr auto cbegin = __cbegin::__fn{};
184 } // namespace ranges::__cpo
185 
186 namespace ranges::__cend {
187   struct __fn {
188     template <class _Tp>
189     requires invocable<decltype(ranges::end), _Tp const&>
operator__fn190     [[nodiscard]] constexpr auto operator()(_Tp& __t) const
191     noexcept(noexcept(ranges::end(_VSTD::as_const(__t))))
192     {
193       return ranges::end(_VSTD::as_const(__t));
194     }
195 
196     template <class _Tp>
197     requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::end), _Tp const&&>
operator__fn198     [[nodiscard]] constexpr auto operator()(_Tp&& __t) const
199     noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t))))
200     {
201       return ranges::end(static_cast<_Tp const&&>(__t));
202     }
203   };
204 } // namespace ranges::__cend
205 
206 namespace ranges::inline __cpo {
207   inline constexpr auto cend = __cend::__fn{};
208 } // namespace ranges::__cpo
209 
210 // clang-format off
211 
212 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
213 
214 _LIBCPP_END_NAMESPACE_STD
215 
216 _LIBCPP_POP_MACROS
217 
218 #endif // _LIBCPP___RANGES_ACCESS_H
219