1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
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 | |
10 | #ifndef _LIBCPP___RANGES_ELEMENTS_VIEW_H |
11 | #define _LIBCPP___RANGES_ELEMENTS_VIEW_H |
12 | |
13 | #include <__compare/three_way_comparable.h> |
14 | #include <__concepts/constructible.h> |
15 | #include <__concepts/convertible_to.h> |
16 | #include <__concepts/derived_from.h> |
17 | #include <__concepts/equality_comparable.h> |
18 | #include <__config> |
19 | #include <__fwd/complex.h> |
20 | #include <__iterator/concepts.h> |
21 | #include <__iterator/iterator_traits.h> |
22 | #include <__ranges/access.h> |
23 | #include <__ranges/all.h> |
24 | #include <__ranges/concepts.h> |
25 | #include <__ranges/enable_borrowed_range.h> |
26 | #include <__ranges/range_adaptor.h> |
27 | #include <__ranges/size.h> |
28 | #include <__ranges/view_interface.h> |
29 | #include <__tuple/tuple_element.h> |
30 | #include <__tuple/tuple_like.h> |
31 | #include <__tuple/tuple_size.h> |
32 | #include <__type_traits/is_reference.h> |
33 | #include <__type_traits/maybe_const.h> |
34 | #include <__type_traits/remove_cv.h> |
35 | #include <__type_traits/remove_cvref.h> |
36 | #include <__type_traits/remove_reference.h> |
37 | #include <__utility/declval.h> |
38 | #include <__utility/forward.h> |
39 | #include <__utility/move.h> |
40 | #include <cstddef> |
41 | |
42 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
43 | # pragma GCC system_header |
44 | #endif |
45 | |
46 | _LIBCPP_PUSH_MACROS |
47 | #include <__undef_macros> |
48 | |
49 | _LIBCPP_BEGIN_NAMESPACE_STD |
50 | |
51 | #if _LIBCPP_STD_VER >= 20 |
52 | |
53 | namespace ranges { |
54 | |
55 | template <class _Tp, size_t _Np> |
56 | concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value; |
57 | |
58 | template <class _Tp, size_t _Np> |
59 | concept __returnable_element = is_reference_v<_Tp> || move_constructible<tuple_element_t<_Np, _Tp>>; |
60 | |
61 | template <input_range _View, size_t _Np> |
62 | requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && |
63 | __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && |
64 | __returnable_element<range_reference_t<_View>, _Np> |
65 | class elements_view : public view_interface<elements_view<_View, _Np>> { |
66 | private: |
67 | template <bool> |
68 | class __iterator; |
69 | |
70 | template <bool> |
71 | class __sentinel; |
72 | |
73 | public: |
74 | _LIBCPP_HIDE_FROM_ABI elements_view() |
75 | requires default_initializable<_View> |
76 | = default; |
77 | |
78 | _LIBCPP_HIDE_FROM_ABI constexpr explicit elements_view(_View __base) : __base_(std::move(__base)) {} |
79 | |
80 | _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& |
81 | requires copy_constructible<_View> |
82 | { |
83 | return __base_; |
84 | } |
85 | |
86 | _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } |
87 | |
88 | _LIBCPP_HIDE_FROM_ABI constexpr auto begin() |
89 | requires(!__simple_view<_View>) |
90 | { |
91 | return __iterator</*_Const=*/false>(ranges::begin(__base_)); |
92 | } |
93 | |
94 | _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const |
95 | requires range<const _View> |
96 | { |
97 | return __iterator</*_Const=*/true>(ranges::begin(__base_)); |
98 | } |
99 | |
100 | _LIBCPP_HIDE_FROM_ABI constexpr auto end() |
101 | requires(!__simple_view<_View> && !common_range<_View>) |
102 | { |
103 | return __sentinel</*_Const=*/false>{ranges::end(__base_)}; |
104 | } |
105 | |
106 | _LIBCPP_HIDE_FROM_ABI constexpr auto end() |
107 | requires(!__simple_view<_View> && common_range<_View>) |
108 | { |
109 | return __iterator</*_Const=*/false>{ranges::end(__base_)}; |
110 | } |
111 | |
112 | _LIBCPP_HIDE_FROM_ABI constexpr auto end() const |
113 | requires range<const _View> |
114 | { |
115 | return __sentinel</*_Const=*/true>{ranges::end(__base_)}; |
116 | } |
117 | |
118 | _LIBCPP_HIDE_FROM_ABI constexpr auto end() const |
119 | requires common_range<const _View> |
120 | { |
121 | return __iterator</*_Const=*/true>{ranges::end(__base_)}; |
122 | } |
123 | |
124 | _LIBCPP_HIDE_FROM_ABI constexpr auto size() |
125 | requires sized_range<_View> |
126 | { |
127 | return ranges::size(__base_); |
128 | } |
129 | |
130 | _LIBCPP_HIDE_FROM_ABI constexpr auto size() const |
131 | requires sized_range<const _View> |
132 | { |
133 | return ranges::size(__base_); |
134 | } |
135 | |
136 | private: |
137 | _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); |
138 | }; |
139 | |
140 | template <class, size_t> |
141 | struct __elements_view_iterator_category_base {}; |
142 | |
143 | template <forward_range _Base, size_t _Np> |
144 | struct __elements_view_iterator_category_base<_Base, _Np> { |
145 | static consteval auto __get_iterator_category() { |
146 | using _Result = decltype(std::get<_Np>(*std::declval<iterator_t<_Base>>())); |
147 | using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; |
148 | |
149 | if constexpr (!is_lvalue_reference_v<_Result>) { |
150 | return input_iterator_tag{}; |
151 | } else if constexpr (derived_from<_Cat, random_access_iterator_tag>) { |
152 | return random_access_iterator_tag{}; |
153 | } else { |
154 | return _Cat{}; |
155 | } |
156 | } |
157 | |
158 | using iterator_category = decltype(__get_iterator_category()); |
159 | }; |
160 | |
161 | template <input_range _View, size_t _Np> |
162 | requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && |
163 | __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && |
164 | __returnable_element<range_reference_t<_View>, _Np> |
165 | template <bool _Const> |
166 | class elements_view<_View, _Np>::__iterator |
167 | : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> { |
168 | template <bool> |
169 | friend class __iterator; |
170 | |
171 | template <bool> |
172 | friend class __sentinel; |
173 | |
174 | using _Base = __maybe_const<_Const, _View>; |
175 | |
176 | iterator_t<_Base> __current_ = iterator_t<_Base>(); |
177 | |
178 | _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) { |
179 | if constexpr (is_reference_v<range_reference_t<_Base>>) { |
180 | return std::get<_Np>(*__i); |
181 | } else { |
182 | using _Element = remove_cv_t<tuple_element_t<_Np, range_reference_t<_Base>>>; |
183 | return static_cast<_Element>(std::get<_Np>(*__i)); |
184 | } |
185 | } |
186 | |
187 | static consteval auto __get_iterator_concept() { |
188 | if constexpr (random_access_range<_Base>) { |
189 | return random_access_iterator_tag{}; |
190 | } else if constexpr (bidirectional_range<_Base>) { |
191 | return bidirectional_iterator_tag{}; |
192 | } else if constexpr (forward_range<_Base>) { |
193 | return forward_iterator_tag{}; |
194 | } else { |
195 | return input_iterator_tag{}; |
196 | } |
197 | } |
198 | |
199 | public: |
200 | using iterator_concept = decltype(__get_iterator_concept()); |
201 | using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>; |
202 | using difference_type = range_difference_t<_Base>; |
203 | |
204 | _LIBCPP_HIDE_FROM_ABI __iterator() |
205 | requires default_initializable<iterator_t<_Base>> |
206 | = default; |
207 | |
208 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {} |
209 | |
210 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) |
211 | requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> |
212 | : __current_(std::move(__i.__current_)) {} |
213 | |
214 | _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; } |
215 | |
216 | _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); } |
217 | |
218 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(i: __current_); } |
219 | |
220 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { |
221 | ++__current_; |
222 | return *this; |
223 | } |
224 | |
225 | _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } |
226 | |
227 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) |
228 | requires forward_range<_Base> |
229 | { |
230 | auto __temp = *this; |
231 | ++__current_; |
232 | return __temp; |
233 | } |
234 | |
235 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() |
236 | requires bidirectional_range<_Base> |
237 | { |
238 | --__current_; |
239 | return *this; |
240 | } |
241 | |
242 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) |
243 | requires bidirectional_range<_Base> |
244 | { |
245 | auto __temp = *this; |
246 | --__current_; |
247 | return __temp; |
248 | } |
249 | |
250 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) |
251 | requires random_access_range<_Base> |
252 | { |
253 | __current_ += __n; |
254 | return *this; |
255 | } |
256 | |
257 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) |
258 | requires random_access_range<_Base> |
259 | { |
260 | __current_ -= __n; |
261 | return *this; |
262 | } |
263 | |
264 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const |
265 | requires random_access_range<_Base> |
266 | { |
267 | return __get_element(i: __current_ + __n); |
268 | } |
269 | |
270 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) |
271 | requires equality_comparable<iterator_t<_Base>> |
272 | { |
273 | return __x.__current_ == __y.__current_; |
274 | } |
275 | |
276 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) |
277 | requires random_access_range<_Base> |
278 | { |
279 | return __x.__current_ < __y.__current_; |
280 | } |
281 | |
282 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) |
283 | requires random_access_range<_Base> |
284 | { |
285 | return __y < __x; |
286 | } |
287 | |
288 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) |
289 | requires random_access_range<_Base> |
290 | { |
291 | return !(__y < __x); |
292 | } |
293 | |
294 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) |
295 | requires random_access_range<_Base> |
296 | { |
297 | return !(__x < __y); |
298 | } |
299 | |
300 | _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) |
301 | requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> |
302 | { |
303 | return __x.__current_ <=> __y.__current_; |
304 | } |
305 | |
306 | _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y) |
307 | requires random_access_range<_Base> |
308 | { |
309 | return __iterator{__x} += __y; |
310 | } |
311 | |
312 | _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y) |
313 | requires random_access_range<_Base> |
314 | { |
315 | return __y + __x; |
316 | } |
317 | |
318 | _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y) |
319 | requires random_access_range<_Base> |
320 | { |
321 | return __iterator{__x} -= __y; |
322 | } |
323 | |
324 | _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) |
325 | requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> |
326 | { |
327 | return __x.__current_ - __y.__current_; |
328 | } |
329 | }; |
330 | |
331 | template <input_range _View, size_t _Np> |
332 | requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> && |
333 | __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> && |
334 | __returnable_element<range_reference_t<_View>, _Np> |
335 | template <bool _Const> |
336 | class elements_view<_View, _Np>::__sentinel { |
337 | private: |
338 | using _Base = __maybe_const<_Const, _View>; |
339 | _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>(); |
340 | |
341 | template <bool> |
342 | friend class __sentinel; |
343 | |
344 | template <bool _AnyConst> |
345 | _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) { |
346 | return (__iter.__current_); |
347 | } |
348 | |
349 | public: |
350 | _LIBCPP_HIDE_FROM_ABI __sentinel() = default; |
351 | |
352 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {} |
353 | |
354 | _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other) |
355 | requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> |
356 | : __end_(std::move(__other.__end_)) {} |
357 | |
358 | _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } |
359 | |
360 | template <bool _OtherConst> |
361 | requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> |
362 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { |
363 | return __get_current(__x) == __y.__end_; |
364 | } |
365 | |
366 | template <bool _OtherConst> |
367 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> |
368 | _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> |
369 | operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { |
370 | return __get_current(__x) - __y.__end_; |
371 | } |
372 | |
373 | template <bool _OtherConst> |
374 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> |
375 | _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> |
376 | operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { |
377 | return __x.__end_ - __get_current(__y); |
378 | } |
379 | }; |
380 | |
381 | template <class _Tp, size_t _Np> |
382 | inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Np>> = enable_borrowed_range<_Tp>; |
383 | |
384 | template <class _Tp> |
385 | using keys_view = elements_view<_Tp, 0>; |
386 | template <class _Tp> |
387 | using values_view = elements_view<_Tp, 1>; |
388 | |
389 | namespace views { |
390 | namespace __elements { |
391 | |
392 | template <size_t _Np> |
393 | struct __fn : __range_adaptor_closure<__fn<_Np>> { |
394 | template <class _Range> |
395 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const |
396 | /**/ noexcept(noexcept(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)))) |
397 | /*------*/ -> decltype(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range))) { |
398 | /*-------------*/ return elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range)); |
399 | } |
400 | }; |
401 | } // namespace __elements |
402 | |
403 | inline namespace __cpo { |
404 | template <size_t _Np> |
405 | inline constexpr auto elements = __elements::__fn<_Np>{}; |
406 | inline constexpr auto keys = elements<0>; |
407 | inline constexpr auto values = elements<1>; |
408 | } // namespace __cpo |
409 | } // namespace views |
410 | } // namespace ranges |
411 | |
412 | #endif // _LIBCPP_STD_VER >= 20 |
413 | |
414 | _LIBCPP_END_NAMESPACE_STD |
415 | |
416 | _LIBCPP_POP_MACROS |
417 | |
418 | #endif // _LIBCPP___RANGES_ELEMENTS_VIEW_H |
419 | |