]>
Commit | Line | Data |
---|---|---|
328b52d6 JW |
1 | // <ranges> -*- C++ -*- |
2 | ||
7adcbafe | 3 | // Copyright (C) 2019-2022 Free Software Foundation, Inc. |
328b52d6 JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
7dbf96e2 JW |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
328b52d6 JW |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
25 | /** @file include/ranges | |
26 | * This is a Standard C++ Library header. | |
27 | * @ingroup concepts | |
28 | */ | |
29 | ||
30 | #ifndef _GLIBCXX_RANGES | |
31 | #define _GLIBCXX_RANGES 1 | |
32 | ||
33 | #if __cplusplus > 201703L | |
34 | ||
35 | #pragma GCC system_header | |
36 | ||
37 | #include <concepts> | |
38 | ||
39 | #if __cpp_lib_concepts | |
40 | ||
37f33df7 JW |
41 | #include <compare> |
42 | #include <initializer_list> | |
328b52d6 | 43 | #include <iterator> |
37f33df7 | 44 | #include <optional> |
9626e447 | 45 | #include <span> |
cba9ef06 | 46 | #include <tuple> |
160061ac JW |
47 | #include <bits/ranges_util.h> |
48 | #include <bits/refwrap.h> | |
328b52d6 JW |
49 | |
50 | /** | |
51 | * @defgroup ranges Ranges | |
52 | * | |
53 | * Components for dealing with ranges of elements. | |
54 | */ | |
55 | ||
56 | namespace std _GLIBCXX_VISIBILITY(default) | |
57 | { | |
58 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
59 | namespace ranges | |
60 | { | |
160061ac JW |
61 | // [range.access] customization point objects |
62 | // [range.req] range and view concepts | |
63 | // [range.dangling] dangling iterator handling | |
64 | // Defined in <bits/ranges_base.h> | |
37f33df7 | 65 | |
160061ac JW |
66 | // [view.interface] View interface |
67 | // [range.subrange] Sub-ranges | |
68 | // Defined in <bits/ranges_util.h> | |
37f33df7 | 69 | |
160061ac | 70 | // C++20 24.6 [range.factories] Range factories |
b5b2e387 | 71 | |
160061ac | 72 | /// A view that contains no elements. |
37f33df7 | 73 | template<typename _Tp> requires is_object_v<_Tp> |
b5b2e387 JW |
74 | class empty_view |
75 | : public view_interface<empty_view<_Tp>> | |
37f33df7 JW |
76 | { |
77 | public: | |
78 | static constexpr _Tp* begin() noexcept { return nullptr; } | |
79 | static constexpr _Tp* end() noexcept { return nullptr; } | |
80 | static constexpr _Tp* data() noexcept { return nullptr; } | |
81 | static constexpr size_t size() noexcept { return 0; } | |
82 | static constexpr bool empty() noexcept { return true; } | |
37f33df7 JW |
83 | }; |
84 | ||
b5b2e387 | 85 | template<typename _Tp> |
15411a64 | 86 | inline constexpr bool enable_borrowed_range<empty_view<_Tp>> = true; |
b5b2e387 | 87 | |
37f33df7 JW |
88 | namespace __detail |
89 | { | |
42907ca9 PP |
90 | template<typename _Tp> |
91 | concept __boxable = copy_constructible<_Tp> && is_object_v<_Tp>; | |
92 | ||
93 | template<__boxable _Tp> | |
37f33df7 JW |
94 | struct __box : std::optional<_Tp> |
95 | { | |
96 | using std::optional<_Tp>::optional; | |
97 | ||
98 | constexpr | |
99 | __box() | |
100 | noexcept(is_nothrow_default_constructible_v<_Tp>) | |
101 | requires default_initializable<_Tp> | |
102 | : std::optional<_Tp>{std::in_place} | |
103 | { } | |
104 | ||
cba9ef06 PP |
105 | __box(const __box&) = default; |
106 | __box(__box&&) = default; | |
107 | ||
37f33df7 JW |
108 | using std::optional<_Tp>::operator=; |
109 | ||
00ffe730 JW |
110 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
111 | // 3477. Simplify constraints for semiregular-box | |
37f33df7 JW |
112 | __box& |
113 | operator=(const __box& __that) | |
114 | noexcept(is_nothrow_copy_constructible_v<_Tp>) | |
00ffe730 | 115 | requires (!copyable<_Tp>) |
37f33df7 | 116 | { |
4b4f5666 PP |
117 | if (this != std::__addressof(__that)) |
118 | { | |
119 | if ((bool)__that) | |
120 | this->emplace(*__that); | |
121 | else | |
122 | this->reset(); | |
123 | } | |
37f33df7 JW |
124 | return *this; |
125 | } | |
126 | ||
127 | __box& | |
128 | operator=(__box&& __that) | |
129 | noexcept(is_nothrow_move_constructible_v<_Tp>) | |
00ffe730 | 130 | requires (!movable<_Tp>) |
37f33df7 | 131 | { |
4b4f5666 PP |
132 | if (this != std::__addressof(__that)) |
133 | { | |
134 | if ((bool)__that) | |
135 | this->emplace(std::move(*__that)); | |
136 | else | |
137 | this->reset(); | |
138 | } | |
37f33df7 JW |
139 | return *this; |
140 | } | |
141 | }; | |
142 | ||
4b4f5666 PP |
143 | // For types which are already copyable, this specialization of the |
144 | // copyable wrapper stores the object directly without going through | |
42907ca9 PP |
145 | // std::optional. It provides just the subset of the primary template's |
146 | // API that we currently use. | |
4b4f5666 PP |
147 | template<__boxable _Tp> |
148 | requires copyable<_Tp> || (is_nothrow_move_constructible_v<_Tp> | |
149 | && is_nothrow_copy_constructible_v<_Tp>) | |
42907ca9 PP |
150 | struct __box<_Tp> |
151 | { | |
152 | private: | |
f3ced677 | 153 | [[no_unique_address]] _Tp _M_value = _Tp(); |
42907ca9 PP |
154 | |
155 | public: | |
4b4f5666 | 156 | __box() requires default_initializable<_Tp> = default; |
42907ca9 PP |
157 | |
158 | constexpr explicit | |
159 | __box(const _Tp& __t) | |
160 | noexcept(is_nothrow_copy_constructible_v<_Tp>) | |
4b4f5666 | 161 | : _M_value(__t) |
42907ca9 PP |
162 | { } |
163 | ||
164 | constexpr explicit | |
165 | __box(_Tp&& __t) | |
166 | noexcept(is_nothrow_move_constructible_v<_Tp>) | |
4b4f5666 | 167 | : _M_value(std::move(__t)) |
42907ca9 PP |
168 | { } |
169 | ||
170 | template<typename... _Args> | |
171 | requires constructible_from<_Tp, _Args...> | |
f3ced677 | 172 | constexpr explicit |
42907ca9 PP |
173 | __box(in_place_t, _Args&&... __args) |
174 | noexcept(is_nothrow_constructible_v<_Tp, _Args...>) | |
fe993b46 | 175 | : _M_value(std::forward<_Args>(__args)...) |
42907ca9 PP |
176 | { } |
177 | ||
4b4f5666 PP |
178 | __box(const __box&) = default; |
179 | __box(__box&&) = default; | |
180 | __box& operator=(const __box&) requires copyable<_Tp> = default; | |
181 | __box& operator=(__box&&) requires copyable<_Tp> = default; | |
182 | ||
183 | // When _Tp is nothrow_copy_constructible but not copy_assignable, | |
184 | // copy assignment is implemented via destroy-then-copy-construct. | |
185 | constexpr __box& | |
186 | operator=(const __box& __that) noexcept | |
187 | { | |
188 | static_assert(is_nothrow_copy_constructible_v<_Tp>); | |
189 | if (this != std::__addressof(__that)) | |
190 | { | |
191 | _M_value.~_Tp(); | |
192 | std::construct_at(std::__addressof(_M_value), *__that); | |
193 | } | |
194 | return *this; | |
195 | } | |
196 | ||
197 | // Likewise for move assignment. | |
198 | constexpr __box& | |
199 | operator=(__box&& __that) noexcept | |
200 | { | |
201 | static_assert(is_nothrow_move_constructible_v<_Tp>); | |
202 | if (this != std::__addressof(__that)) | |
203 | { | |
204 | _M_value.~_Tp(); | |
205 | std::construct_at(std::__addressof(_M_value), std::move(*__that)); | |
206 | } | |
207 | return *this; | |
208 | } | |
209 | ||
42907ca9 PP |
210 | constexpr bool |
211 | has_value() const noexcept | |
212 | { return true; }; | |
213 | ||
214 | constexpr _Tp& | |
215 | operator*() noexcept | |
216 | { return _M_value; } | |
217 | ||
218 | constexpr const _Tp& | |
219 | operator*() const noexcept | |
220 | { return _M_value; } | |
221 | ||
222 | constexpr _Tp* | |
223 | operator->() noexcept | |
fe993b46 | 224 | { return std::__addressof(_M_value); } |
42907ca9 PP |
225 | |
226 | constexpr const _Tp* | |
227 | operator->() const noexcept | |
fe993b46 | 228 | { return std::__addressof(_M_value); } |
42907ca9 | 229 | }; |
37f33df7 JW |
230 | } // namespace __detail |
231 | ||
232 | /// A view that contains exactly one element. | |
233 | template<copy_constructible _Tp> requires is_object_v<_Tp> | |
234 | class single_view : public view_interface<single_view<_Tp>> | |
235 | { | |
236 | public: | |
4b4f5666 | 237 | single_view() requires default_initializable<_Tp> = default; |
37f33df7 JW |
238 | |
239 | constexpr explicit | |
240 | single_view(const _Tp& __t) | |
9245b0e8 | 241 | noexcept(is_nothrow_copy_constructible_v<_Tp>) |
37f33df7 JW |
242 | : _M_value(__t) |
243 | { } | |
244 | ||
245 | constexpr explicit | |
246 | single_view(_Tp&& __t) | |
9245b0e8 | 247 | noexcept(is_nothrow_move_constructible_v<_Tp>) |
37f33df7 JW |
248 | : _M_value(std::move(__t)) |
249 | { } | |
250 | ||
50106208 PP |
251 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
252 | // 3428. single_view's in place constructor should be explicit | |
37f33df7 JW |
253 | template<typename... _Args> |
254 | requires constructible_from<_Tp, _Args...> | |
50106208 | 255 | constexpr explicit |
37f33df7 | 256 | single_view(in_place_t, _Args&&... __args) |
9245b0e8 | 257 | noexcept(is_nothrow_constructible_v<_Tp, _Args...>) |
37f33df7 JW |
258 | : _M_value{in_place, std::forward<_Args>(__args)...} |
259 | { } | |
260 | ||
261 | constexpr _Tp* | |
262 | begin() noexcept | |
263 | { return data(); } | |
264 | ||
265 | constexpr const _Tp* | |
266 | begin() const noexcept | |
267 | { return data(); } | |
268 | ||
269 | constexpr _Tp* | |
270 | end() noexcept | |
271 | { return data() + 1; } | |
272 | ||
273 | constexpr const _Tp* | |
274 | end() const noexcept | |
275 | { return data() + 1; } | |
276 | ||
277 | static constexpr size_t | |
278 | size() noexcept | |
279 | { return 1; } | |
280 | ||
281 | constexpr _Tp* | |
282 | data() noexcept | |
283 | { return _M_value.operator->(); } | |
284 | ||
285 | constexpr const _Tp* | |
286 | data() const noexcept | |
287 | { return _M_value.operator->(); } | |
288 | ||
289 | private: | |
42907ca9 | 290 | [[no_unique_address]] __detail::__box<_Tp> _M_value; |
37f33df7 JW |
291 | }; |
292 | ||
6e00d9bb PP |
293 | template<typename _Tp> |
294 | single_view(_Tp) -> single_view<_Tp>; | |
295 | ||
37f33df7 JW |
296 | namespace __detail |
297 | { | |
298 | template<typename _Wp> | |
299 | constexpr auto __to_signed_like(_Wp __w) noexcept | |
300 | { | |
301 | if constexpr (!integral<_Wp>) | |
302 | return iter_difference_t<_Wp>(); | |
303 | else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) | |
304 | return iter_difference_t<_Wp>(__w); | |
305 | else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) | |
306 | return ptrdiff_t(__w); | |
307 | else if constexpr (sizeof(long long) > sizeof(_Wp)) | |
308 | return (long long)(__w); | |
309 | #ifdef __SIZEOF_INT128__ | |
310 | else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) | |
311 | return __int128(__w); | |
312 | #endif | |
313 | else | |
314 | return __max_diff_type(__w); | |
315 | } | |
316 | ||
317 | template<typename _Wp> | |
318 | using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>())); | |
319 | ||
320 | template<typename _It> | |
321 | concept __decrementable = incrementable<_It> | |
322 | && requires(_It __i) | |
323 | { | |
324 | { --__i } -> same_as<_It&>; | |
325 | { __i-- } -> same_as<_It>; | |
326 | }; | |
327 | ||
328 | template<typename _It> | |
329 | concept __advanceable = __decrementable<_It> && totally_ordered<_It> | |
330 | && requires( _It __i, const _It __j, const __iota_diff_t<_It> __n) | |
331 | { | |
332 | { __i += __n } -> same_as<_It&>; | |
333 | { __i -= __n } -> same_as<_It&>; | |
334 | _It(__j + __n); | |
335 | _It(__n + __j); | |
336 | _It(__j - __n); | |
337 | { __j - __j } -> convertible_to<__iota_diff_t<_It>>; | |
338 | }; | |
339 | ||
902b40c7 PP |
340 | template<typename _Winc> |
341 | struct __iota_view_iter_cat | |
342 | { }; | |
343 | ||
344 | template<incrementable _Winc> | |
345 | struct __iota_view_iter_cat<_Winc> | |
346 | { using iterator_category = input_iterator_tag; }; | |
37f33df7 JW |
347 | } // namespace __detail |
348 | ||
349 | template<weakly_incrementable _Winc, | |
350 | semiregular _Bound = unreachable_sentinel_t> | |
351 | requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound> | |
4b4f5666 | 352 | && copyable<_Winc> |
37f33df7 JW |
353 | class iota_view : public view_interface<iota_view<_Winc, _Bound>> |
354 | { | |
355 | private: | |
5586e506 PP |
356 | struct _Sentinel; |
357 | ||
902b40c7 | 358 | struct _Iterator : __detail::__iota_view_iter_cat<_Winc> |
37f33df7 JW |
359 | { |
360 | private: | |
361 | static auto | |
902b40c7 | 362 | _S_iter_concept() |
37f33df7 JW |
363 | { |
364 | using namespace __detail; | |
365 | if constexpr (__advanceable<_Winc>) | |
366 | return random_access_iterator_tag{}; | |
367 | else if constexpr (__decrementable<_Winc>) | |
368 | return bidirectional_iterator_tag{}; | |
369 | else if constexpr (incrementable<_Winc>) | |
370 | return forward_iterator_tag{}; | |
371 | else | |
372 | return input_iterator_tag{}; | |
373 | } | |
374 | ||
375 | public: | |
902b40c7 PP |
376 | using iterator_concept = decltype(_S_iter_concept()); |
377 | // iterator_category defined in __iota_view_iter_cat | |
37f33df7 JW |
378 | using value_type = _Winc; |
379 | using difference_type = __detail::__iota_diff_t<_Winc>; | |
380 | ||
4b4f5666 | 381 | _Iterator() requires default_initializable<_Winc> = default; |
37f33df7 JW |
382 | |
383 | constexpr explicit | |
384 | _Iterator(_Winc __value) | |
385 | : _M_value(__value) { } | |
386 | ||
387 | constexpr _Winc | |
388 | operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>) | |
389 | { return _M_value; } | |
390 | ||
391 | constexpr _Iterator& | |
392 | operator++() | |
393 | { | |
394 | ++_M_value; | |
395 | return *this; | |
396 | } | |
397 | ||
398 | constexpr void | |
399 | operator++(int) | |
400 | { ++*this; } | |
401 | ||
402 | constexpr _Iterator | |
403 | operator++(int) requires incrementable<_Winc> | |
404 | { | |
405 | auto __tmp = *this; | |
406 | ++*this; | |
407 | return __tmp; | |
408 | } | |
409 | ||
410 | constexpr _Iterator& | |
411 | operator--() requires __detail::__decrementable<_Winc> | |
412 | { | |
413 | --_M_value; | |
414 | return *this; | |
415 | } | |
416 | ||
417 | constexpr _Iterator | |
418 | operator--(int) requires __detail::__decrementable<_Winc> | |
419 | { | |
420 | auto __tmp = *this; | |
421 | --*this; | |
422 | return __tmp; | |
423 | } | |
424 | ||
425 | constexpr _Iterator& | |
426 | operator+=(difference_type __n) requires __detail::__advanceable<_Winc> | |
427 | { | |
2a0f6c61 JW |
428 | using __detail::__is_integer_like; |
429 | using __detail::__is_signed_integer_like; | |
37f33df7 JW |
430 | if constexpr (__is_integer_like<_Winc> |
431 | && !__is_signed_integer_like<_Winc>) | |
432 | { | |
433 | if (__n >= difference_type(0)) | |
434 | _M_value += static_cast<_Winc>(__n); | |
435 | else | |
436 | _M_value -= static_cast<_Winc>(-__n); | |
437 | } | |
438 | else | |
439 | _M_value += __n; | |
440 | return *this; | |
441 | } | |
442 | ||
443 | constexpr _Iterator& | |
444 | operator-=(difference_type __n) requires __detail::__advanceable<_Winc> | |
445 | { | |
2a0f6c61 JW |
446 | using __detail::__is_integer_like; |
447 | using __detail::__is_signed_integer_like; | |
37f33df7 JW |
448 | if constexpr (__is_integer_like<_Winc> |
449 | && !__is_signed_integer_like<_Winc>) | |
450 | { | |
451 | if (__n >= difference_type(0)) | |
452 | _M_value -= static_cast<_Winc>(__n); | |
453 | else | |
454 | _M_value += static_cast<_Winc>(-__n); | |
455 | } | |
456 | else | |
457 | _M_value -= __n; | |
458 | return *this; | |
459 | } | |
460 | ||
461 | constexpr _Winc | |
462 | operator[](difference_type __n) const | |
463 | requires __detail::__advanceable<_Winc> | |
464 | { return _Winc(_M_value + __n); } | |
465 | ||
466 | friend constexpr bool | |
467 | operator==(const _Iterator& __x, const _Iterator& __y) | |
468 | requires equality_comparable<_Winc> | |
469 | { return __x._M_value == __y._M_value; } | |
470 | ||
471 | friend constexpr bool | |
472 | operator<(const _Iterator& __x, const _Iterator& __y) | |
473 | requires totally_ordered<_Winc> | |
474 | { return __x._M_value < __y._M_value; } | |
475 | ||
476 | friend constexpr bool | |
477 | operator>(const _Iterator& __x, const _Iterator& __y) | |
478 | requires totally_ordered<_Winc> | |
479 | { return __y < __x; } | |
480 | ||
481 | friend constexpr bool | |
482 | operator<=(const _Iterator& __x, const _Iterator& __y) | |
483 | requires totally_ordered<_Winc> | |
484 | { return !(__y < __x); } | |
485 | ||
486 | friend constexpr bool | |
487 | operator>=(const _Iterator& __x, const _Iterator& __y) | |
488 | requires totally_ordered<_Winc> | |
489 | { return !(__x < __y); } | |
490 | ||
5713834e JW |
491 | #ifdef __cpp_lib_three_way_comparison |
492 | friend constexpr auto | |
37f33df7 JW |
493 | operator<=>(const _Iterator& __x, const _Iterator& __y) |
494 | requires totally_ordered<_Winc> && three_way_comparable<_Winc> | |
495 | { return __x._M_value <=> __y._M_value; } | |
496 | #endif | |
497 | ||
498 | friend constexpr _Iterator | |
499 | operator+(_Iterator __i, difference_type __n) | |
500 | requires __detail::__advanceable<_Winc> | |
5566f3c6 PP |
501 | { |
502 | __i += __n; | |
503 | return __i; | |
504 | } | |
37f33df7 JW |
505 | |
506 | friend constexpr _Iterator | |
507 | operator+(difference_type __n, _Iterator __i) | |
508 | requires __detail::__advanceable<_Winc> | |
509 | { return __i += __n; } | |
510 | ||
511 | friend constexpr _Iterator | |
512 | operator-(_Iterator __i, difference_type __n) | |
513 | requires __detail::__advanceable<_Winc> | |
5566f3c6 PP |
514 | { |
515 | __i -= __n; | |
516 | return __i; | |
517 | } | |
37f33df7 JW |
518 | |
519 | friend constexpr difference_type | |
520 | operator-(const _Iterator& __x, const _Iterator& __y) | |
521 | requires __detail::__advanceable<_Winc> | |
522 | { | |
2a0f6c61 JW |
523 | using __detail::__is_integer_like; |
524 | using __detail::__is_signed_integer_like; | |
37f33df7 JW |
525 | using _Dt = difference_type; |
526 | if constexpr (__is_integer_like<_Winc>) | |
527 | { | |
528 | if constexpr (__is_signed_integer_like<_Winc>) | |
529 | return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value)); | |
530 | else | |
531 | return (__y._M_value > __x._M_value) | |
532 | ? _Dt(-_Dt(__y._M_value - __x._M_value)) | |
533 | : _Dt(__x._M_value - __y._M_value); | |
534 | } | |
535 | else | |
536 | return __x._M_value - __y._M_value; | |
537 | } | |
538 | ||
539 | private: | |
540 | _Winc _M_value = _Winc(); | |
5586e506 | 541 | |
861440a7 | 542 | friend iota_view; |
5586e506 | 543 | friend _Sentinel; |
37f33df7 JW |
544 | }; |
545 | ||
546 | struct _Sentinel | |
547 | { | |
548 | private: | |
5586e506 PP |
549 | constexpr bool |
550 | _M_equal(const _Iterator& __x) const | |
551 | { return __x._M_value == _M_bound; } | |
552 | ||
317a38cd PP |
553 | constexpr auto |
554 | _M_distance_from(const _Iterator& __x) const | |
555 | { return _M_bound - __x._M_value; } | |
556 | ||
37f33df7 JW |
557 | _Bound _M_bound = _Bound(); |
558 | ||
559 | public: | |
560 | _Sentinel() = default; | |
561 | ||
562 | constexpr explicit | |
563 | _Sentinel(_Bound __bound) | |
564 | : _M_bound(__bound) { } | |
565 | ||
566 | friend constexpr bool | |
567 | operator==(const _Iterator& __x, const _Sentinel& __y) | |
5586e506 | 568 | { return __y._M_equal(__x); } |
37f33df7 JW |
569 | |
570 | friend constexpr iter_difference_t<_Winc> | |
571 | operator-(const _Iterator& __x, const _Sentinel& __y) | |
572 | requires sized_sentinel_for<_Bound, _Winc> | |
317a38cd | 573 | { return -__y._M_distance_from(__x); } |
37f33df7 JW |
574 | |
575 | friend constexpr iter_difference_t<_Winc> | |
576 | operator-(const _Sentinel& __x, const _Iterator& __y) | |
577 | requires sized_sentinel_for<_Bound, _Winc> | |
317a38cd | 578 | { return __x._M_distance_from(__y); } |
861440a7 PP |
579 | |
580 | friend iota_view; | |
37f33df7 JW |
581 | }; |
582 | ||
583 | _Winc _M_value = _Winc(); | |
62344335 | 584 | [[no_unique_address]] _Bound _M_bound = _Bound(); |
37f33df7 JW |
585 | |
586 | public: | |
4b4f5666 | 587 | iota_view() requires default_initializable<_Winc> = default; |
37f33df7 JW |
588 | |
589 | constexpr explicit | |
590 | iota_view(_Winc __value) | |
591 | : _M_value(__value) | |
592 | { } | |
593 | ||
594 | constexpr | |
595 | iota_view(type_identity_t<_Winc> __value, | |
596 | type_identity_t<_Bound> __bound) | |
597 | : _M_value(__value), _M_bound(__bound) | |
598 | { | |
599 | if constexpr (totally_ordered_with<_Winc, _Bound>) | |
10f51543 | 600 | __glibcxx_assert( bool(__value <= __bound) ); |
37f33df7 JW |
601 | } |
602 | ||
861440a7 PP |
603 | constexpr |
604 | iota_view(_Iterator __first, _Iterator __last) | |
605 | requires same_as<_Winc, _Bound> | |
606 | : iota_view(__first._M_value, __last._M_value) | |
607 | { } | |
608 | ||
609 | constexpr | |
610 | iota_view(_Iterator __first, unreachable_sentinel_t __last) | |
611 | requires same_as<_Bound, unreachable_sentinel_t> | |
612 | : iota_view(__first._M_value, __last) | |
613 | { } | |
614 | ||
615 | constexpr | |
616 | iota_view(_Iterator __first, _Sentinel __last) | |
617 | requires (!same_as<_Winc, _Bound>) && (!same_as<_Bound, unreachable_sentinel_t>) | |
618 | : iota_view(__first._M_value, __last._M_bound) | |
619 | { } | |
620 | ||
37f33df7 JW |
621 | constexpr _Iterator |
622 | begin() const { return _Iterator{_M_value}; } | |
623 | ||
624 | constexpr auto | |
625 | end() const | |
626 | { | |
627 | if constexpr (same_as<_Bound, unreachable_sentinel_t>) | |
628 | return unreachable_sentinel; | |
629 | else | |
630 | return _Sentinel{_M_bound}; | |
631 | } | |
632 | ||
633 | constexpr _Iterator | |
634 | end() const requires same_as<_Winc, _Bound> | |
635 | { return _Iterator{_M_bound}; } | |
636 | ||
637 | constexpr auto | |
638 | size() const | |
639 | requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>) | |
640 | || (integral<_Winc> && integral<_Bound>) | |
641 | || sized_sentinel_for<_Bound, _Winc> | |
642 | { | |
2a0f6c61 JW |
643 | using __detail::__is_integer_like; |
644 | using __detail::__to_unsigned_like; | |
a0e6f05d JW |
645 | if constexpr (integral<_Winc> && integral<_Bound>) |
646 | { | |
647 | using _Up = make_unsigned_t<decltype(_M_bound - _M_value)>; | |
648 | return _Up(_M_bound) - _Up(_M_value); | |
649 | } | |
650 | else if constexpr (__is_integer_like<_Winc>) | |
651 | return __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value); | |
37f33df7 JW |
652 | else |
653 | return __to_unsigned_like(_M_bound - _M_value); | |
654 | } | |
655 | }; | |
656 | ||
657 | template<typename _Winc, typename _Bound> | |
658 | requires (!__detail::__is_integer_like<_Winc> | |
659 | || !__detail::__is_integer_like<_Bound> | |
660 | || (__detail::__is_signed_integer_like<_Winc> | |
661 | == __detail::__is_signed_integer_like<_Bound>)) | |
662 | iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>; | |
663 | ||
2b71ca68 | 664 | template<typename _Winc, typename _Bound> |
15411a64 JW |
665 | inline constexpr bool |
666 | enable_borrowed_range<iota_view<_Winc, _Bound>> = true; | |
b5b2e387 | 667 | |
37f33df7 JW |
668 | namespace views |
669 | { | |
670 | template<typename _Tp> | |
671 | inline constexpr empty_view<_Tp> empty{}; | |
672 | ||
673 | struct _Single | |
674 | { | |
675 | template<typename _Tp> | |
240b01b0 | 676 | [[nodiscard]] |
cba9ef06 | 677 | constexpr auto |
37f33df7 | 678 | operator()(_Tp&& __e) const |
9245b0e8 | 679 | noexcept(noexcept(single_view<decay_t<_Tp>>(std::forward<_Tp>(__e)))) |
6e00d9bb | 680 | { return single_view<decay_t<_Tp>>(std::forward<_Tp>(__e)); } |
37f33df7 JW |
681 | }; |
682 | ||
683 | inline constexpr _Single single{}; | |
684 | ||
685 | struct _Iota | |
686 | { | |
687 | template<typename _Tp> | |
240b01b0 | 688 | [[nodiscard]] |
cba9ef06 | 689 | constexpr auto |
37f33df7 | 690 | operator()(_Tp&& __e) const |
6e00d9bb | 691 | { return iota_view(std::forward<_Tp>(__e)); } |
37f33df7 JW |
692 | |
693 | template<typename _Tp, typename _Up> | |
240b01b0 | 694 | [[nodiscard]] |
cba9ef06 | 695 | constexpr auto |
37f33df7 | 696 | operator()(_Tp&& __e, _Up&& __f) const |
6e00d9bb | 697 | { return iota_view(std::forward<_Tp>(__e), std::forward<_Up>(__f)); } |
37f33df7 JW |
698 | }; |
699 | ||
700 | inline constexpr _Iota iota{}; | |
cba9ef06 PP |
701 | } // namespace views |
702 | ||
b7903d9f PP |
703 | namespace __detail |
704 | { | |
705 | template<typename _Val, typename _CharT, typename _Traits> | |
706 | concept __stream_extractable | |
707 | = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; }; | |
708 | } // namespace __detail | |
709 | ||
1a129376 JW |
710 | template<movable _Val, typename _CharT, |
711 | typename _Traits = char_traits<_CharT>> | |
b7903d9f PP |
712 | requires default_initializable<_Val> |
713 | && __detail::__stream_extractable<_Val, _CharT, _Traits> | |
714 | class basic_istream_view | |
715 | : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> | |
716 | { | |
717 | public: | |
b7903d9f PP |
718 | constexpr explicit |
719 | basic_istream_view(basic_istream<_CharT, _Traits>& __stream) | |
720 | : _M_stream(std::__addressof(__stream)) | |
721 | { } | |
722 | ||
723 | constexpr auto | |
724 | begin() | |
725 | { | |
4b4f5666 | 726 | *_M_stream >> _M_object; |
afb8da7f | 727 | return _Iterator{this}; |
b7903d9f PP |
728 | } |
729 | ||
730 | constexpr default_sentinel_t | |
731 | end() const noexcept | |
732 | { return default_sentinel; } | |
733 | ||
734 | private: | |
4b4f5666 | 735 | basic_istream<_CharT, _Traits>* _M_stream; |
bed1892f | 736 | _Val _M_object = _Val(); |
b7903d9f PP |
737 | |
738 | struct _Iterator | |
739 | { | |
740 | public: | |
76a8c0f6 | 741 | using iterator_concept = input_iterator_tag; |
b7903d9f PP |
742 | using difference_type = ptrdiff_t; |
743 | using value_type = _Val; | |
744 | ||
b7903d9f | 745 | constexpr explicit |
afb8da7f PP |
746 | _Iterator(basic_istream_view* __parent) noexcept |
747 | : _M_parent(__parent) | |
b7903d9f PP |
748 | { } |
749 | ||
750 | _Iterator(const _Iterator&) = delete; | |
751 | _Iterator(_Iterator&&) = default; | |
752 | _Iterator& operator=(const _Iterator&) = delete; | |
753 | _Iterator& operator=(_Iterator&&) = default; | |
754 | ||
755 | _Iterator& | |
756 | operator++() | |
757 | { | |
b7903d9f | 758 | *_M_parent->_M_stream >> _M_parent->_M_object; |
572992c8 | 759 | return *this; |
b7903d9f PP |
760 | } |
761 | ||
762 | void | |
763 | operator++(int) | |
764 | { ++*this; } | |
765 | ||
766 | _Val& | |
767 | operator*() const | |
4b4f5666 | 768 | { return _M_parent->_M_object; } |
b7903d9f PP |
769 | |
770 | friend bool | |
771 | operator==(const _Iterator& __x, default_sentinel_t) | |
772 | { return __x._M_at_end(); } | |
773 | ||
774 | private: | |
4b4f5666 | 775 | basic_istream_view* _M_parent; |
b7903d9f PP |
776 | |
777 | bool | |
778 | _M_at_end() const | |
4b4f5666 | 779 | { return !*_M_parent->_M_stream; } |
b7903d9f PP |
780 | }; |
781 | ||
782 | friend _Iterator; | |
783 | }; | |
784 | ||
48154969 PP |
785 | template<typename _Val> |
786 | using istream_view = basic_istream_view<_Val, char>; | |
787 | ||
788 | template<typename _Val> | |
789 | using wistream_view = basic_istream_view<_Val, wchar_t>; | |
790 | ||
791 | namespace views | |
792 | { | |
793 | template<typename _Tp> | |
794 | struct _Istream | |
795 | { | |
796 | template<typename _CharT, typename _Traits> | |
797 | [[nodiscard]] | |
798 | constexpr auto | |
799 | operator()(basic_istream<_CharT, _Traits>& __e) const | |
800 | { return basic_istream_view<_Tp, _CharT, _Traits>(__e); } | |
801 | }; | |
802 | ||
803 | template<typename _Tp> | |
804 | inline constexpr _Istream<_Tp> istream; | |
805 | } | |
b7903d9f | 806 | |
160061ac JW |
807 | // C++20 24.7 [range.adaptors] Range adaptors |
808 | ||
cba9ef06 PP |
809 | namespace __detail |
810 | { | |
811 | struct _Empty { }; | |
8017d95c | 812 | |
4c391563 JW |
813 | // Alias for a type that is conditionally present |
814 | // (and is an empty type otherwise). | |
815 | // Data members using this alias should use [[no_unique_address]] so that | |
816 | // they take no space when not needed. | |
817 | template<bool _Present, typename _Tp> | |
a09bb4a8 | 818 | using __maybe_present_t = __conditional_t<_Present, _Tp, _Empty>; |
4c391563 JW |
819 | |
820 | // Alias for a type that is conditionally const. | |
8017d95c | 821 | template<bool _Const, typename _Tp> |
a09bb4a8 | 822 | using __maybe_const_t = __conditional_t<_Const, const _Tp, _Tp>; |
8017d95c | 823 | |
cba9ef06 PP |
824 | } // namespace __detail |
825 | ||
a25321ca | 826 | namespace views::__adaptor |
cba9ef06 | 827 | { |
a25321ca PP |
828 | // True if the range adaptor _Adaptor can be applied with _Args. |
829 | template<typename _Adaptor, typename... _Args> | |
830 | concept __adaptor_invocable | |
831 | = requires { std::declval<_Adaptor>()(declval<_Args>()...); }; | |
832 | ||
833 | // True if the range adaptor non-closure _Adaptor can be partially applied | |
834 | // with _Args. | |
835 | template<typename _Adaptor, typename... _Args> | |
836 | concept __adaptor_partial_app_viable = (_Adaptor::_S_arity > 1) | |
837 | && (sizeof...(_Args) == _Adaptor::_S_arity - 1) | |
838 | && (constructible_from<decay_t<_Args>, _Args> && ...); | |
839 | ||
840 | template<typename _Adaptor, typename... _Args> | |
841 | struct _Partial; | |
842 | ||
843 | template<typename _Lhs, typename _Rhs> | |
844 | struct _Pipe; | |
845 | ||
846 | // The base class of every range adaptor closure. | |
57ed620e PP |
847 | // |
848 | // The derived class should define the optional static data member | |
849 | // _S_has_simple_call_op to true if the behavior of this adaptor is | |
850 | // independent of the constness/value category of the adaptor object. | |
a25321ca | 851 | struct _RangeAdaptorClosure |
cba9ef06 | 852 | { |
a25321ca PP |
853 | // range | adaptor is equivalent to adaptor(range). |
854 | template<typename _Self, typename _Range> | |
855 | requires derived_from<remove_cvref_t<_Self>, _RangeAdaptorClosure> | |
856 | && __adaptor_invocable<_Self, _Range> | |
857 | friend constexpr auto | |
858 | operator|(_Range&& __r, _Self&& __self) | |
859 | { return std::forward<_Self>(__self)(std::forward<_Range>(__r)); } | |
860 | ||
861 | // Compose the adaptors __lhs and __rhs into a pipeline, returning | |
862 | // another range adaptor closure object. | |
863 | template<typename _Lhs, typename _Rhs> | |
864 | requires derived_from<_Lhs, _RangeAdaptorClosure> | |
865 | && derived_from<_Rhs, _RangeAdaptorClosure> | |
866 | friend constexpr auto | |
867 | operator|(_Lhs __lhs, _Rhs __rhs) | |
868 | { return _Pipe<_Lhs, _Rhs>{std::move(__lhs), std::move(__rhs)}; } | |
869 | }; | |
6e63438a | 870 | |
a25321ca PP |
871 | // The base class of every range adaptor non-closure. |
872 | // | |
873 | // The static data member _Derived::_S_arity must contain the total number of | |
874 | // arguments that the adaptor takes, and the class _Derived must introduce | |
875 | // _RangeAdaptor::operator() into the class scope via a using-declaration. | |
57ed620e PP |
876 | // |
877 | // The optional static data member _Derived::_S_has_simple_extra_args should | |
878 | // be defined to true if the behavior of this adaptor is independent of the | |
0f4a2fb4 PP |
879 | // constness/value category of the extra arguments. This data member could |
880 | // also be defined as a variable template parameterized by the types of the | |
881 | // extra arguments. | |
a25321ca PP |
882 | template<typename _Derived> |
883 | struct _RangeAdaptor | |
884 | { | |
885 | // Partially apply the arguments __args to the range adaptor _Derived, | |
886 | // returning a range adaptor closure object. | |
887 | template<typename... _Args> | |
888 | requires __adaptor_partial_app_viable<_Derived, _Args...> | |
889 | constexpr auto | |
890 | operator()(_Args&&... __args) const | |
891 | { | |
892 | return _Partial<_Derived, decay_t<_Args>...>{std::forward<_Args>(__args)...}; | |
893 | } | |
894 | }; | |
6e63438a | 895 | |
57ed620e PP |
896 | // True if the range adaptor closure _Adaptor has a simple operator(), i.e. |
897 | // one that's not overloaded according to constness or value category of the | |
898 | // _Adaptor object. | |
899 | template<typename _Adaptor> | |
900 | concept __closure_has_simple_call_op = _Adaptor::_S_has_simple_call_op; | |
901 | ||
902 | // True if the behavior of the range adaptor non-closure _Adaptor is | |
0f4a2fb4 PP |
903 | // independent of the value category of its extra arguments _Args. |
904 | template<typename _Adaptor, typename... _Args> | |
905 | concept __adaptor_has_simple_extra_args = _Adaptor::_S_has_simple_extra_args | |
906 | || _Adaptor::template _S_has_simple_extra_args<_Args...>; | |
57ed620e | 907 | |
a25321ca PP |
908 | // A range adaptor closure that represents partial application of |
909 | // the range adaptor _Adaptor with arguments _Args. | |
910 | template<typename _Adaptor, typename... _Args> | |
911 | struct _Partial : _RangeAdaptorClosure | |
912 | { | |
913 | tuple<_Args...> _M_args; | |
6e63438a | 914 | |
a25321ca PP |
915 | constexpr |
916 | _Partial(_Args... __args) | |
917 | : _M_args(std::move(__args)...) | |
918 | { } | |
cba9ef06 | 919 | |
a25321ca | 920 | // Invoke _Adaptor with arguments __r, _M_args... according to the |
57ed620e | 921 | // value category of this _Partial object. |
a25321ca PP |
922 | template<typename _Range> |
923 | requires __adaptor_invocable<_Adaptor, _Range, const _Args&...> | |
924 | constexpr auto | |
925 | operator()(_Range&& __r) const & | |
926 | { | |
927 | auto __forwarder = [&__r] (const auto&... __args) { | |
928 | return _Adaptor{}(std::forward<_Range>(__r), __args...); | |
929 | }; | |
930 | return std::apply(__forwarder, _M_args); | |
931 | } | |
cba9ef06 | 932 | |
a25321ca PP |
933 | template<typename _Range> |
934 | requires __adaptor_invocable<_Adaptor, _Range, _Args...> | |
935 | constexpr auto | |
936 | operator()(_Range&& __r) && | |
937 | { | |
938 | auto __forwarder = [&__r] (auto&... __args) { | |
939 | return _Adaptor{}(std::forward<_Range>(__r), std::move(__args)...); | |
940 | }; | |
941 | return std::apply(__forwarder, _M_args); | |
942 | } | |
cba9ef06 | 943 | |
a25321ca PP |
944 | template<typename _Range> |
945 | constexpr auto | |
946 | operator()(_Range&& __r) const && = delete; | |
947 | }; | |
cba9ef06 | 948 | |
a25321ca PP |
949 | // A lightweight specialization of the above primary template for |
950 | // the common case where _Adaptor accepts a single extra argument. | |
951 | template<typename _Adaptor, typename _Arg> | |
952 | struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure | |
953 | { | |
954 | _Arg _M_arg; | |
cba9ef06 | 955 | |
a25321ca PP |
956 | constexpr |
957 | _Partial(_Arg __arg) | |
958 | : _M_arg(std::move(__arg)) | |
959 | { } | |
a5b213dd | 960 | |
a25321ca PP |
961 | template<typename _Range> |
962 | requires __adaptor_invocable<_Adaptor, _Range, const _Arg&> | |
963 | constexpr auto | |
964 | operator()(_Range&& __r) const & | |
965 | { return _Adaptor{}(std::forward<_Range>(__r), _M_arg); } | |
966 | ||
967 | template<typename _Range> | |
968 | requires __adaptor_invocable<_Adaptor, _Range, _Arg> | |
969 | constexpr auto | |
970 | operator()(_Range&& __r) && | |
971 | { return _Adaptor{}(std::forward<_Range>(__r), std::move(_M_arg)); } | |
972 | ||
973 | template<typename _Range> | |
974 | constexpr auto | |
975 | operator()(_Range&& __r) const && = delete; | |
976 | }; | |
cba9ef06 | 977 | |
57ed620e | 978 | // Partial specialization of the primary template for the case where the extra |
2b87f331 PP |
979 | // arguments of the adaptor can always be safely and efficiently forwarded by |
980 | // const reference. This lets us get away with a single operator() overload, | |
981 | // which makes overload resolution failure diagnostics more concise. | |
57ed620e | 982 | template<typename _Adaptor, typename... _Args> |
0f4a2fb4 | 983 | requires __adaptor_has_simple_extra_args<_Adaptor, _Args...> |
2b87f331 | 984 | && (is_trivially_copyable_v<_Args> && ...) |
57ed620e PP |
985 | struct _Partial<_Adaptor, _Args...> : _RangeAdaptorClosure |
986 | { | |
987 | tuple<_Args...> _M_args; | |
988 | ||
989 | constexpr | |
990 | _Partial(_Args... __args) | |
991 | : _M_args(std::move(__args)...) | |
992 | { } | |
993 | ||
994 | // Invoke _Adaptor with arguments __r, const _M_args&... regardless | |
995 | // of the value category of this _Partial object. | |
996 | template<typename _Range> | |
997 | requires __adaptor_invocable<_Adaptor, _Range, const _Args&...> | |
998 | constexpr auto | |
999 | operator()(_Range&& __r) const | |
1000 | { | |
1001 | auto __forwarder = [&__r] (const auto&... __args) { | |
1002 | return _Adaptor{}(std::forward<_Range>(__r), __args...); | |
1003 | }; | |
1004 | return std::apply(__forwarder, _M_args); | |
1005 | } | |
1006 | ||
1007 | static constexpr bool _S_has_simple_call_op = true; | |
1008 | }; | |
1009 | ||
1010 | // A lightweight specialization of the above template for the common case | |
1011 | // where _Adaptor accepts a single extra argument. | |
1012 | template<typename _Adaptor, typename _Arg> | |
0f4a2fb4 | 1013 | requires __adaptor_has_simple_extra_args<_Adaptor, _Arg> |
2b87f331 | 1014 | && is_trivially_copyable_v<_Arg> |
57ed620e PP |
1015 | struct _Partial<_Adaptor, _Arg> : _RangeAdaptorClosure |
1016 | { | |
1017 | _Arg _M_arg; | |
1018 | ||
1019 | constexpr | |
1020 | _Partial(_Arg __arg) | |
1021 | : _M_arg(std::move(__arg)) | |
1022 | { } | |
1023 | ||
1024 | template<typename _Range> | |
1025 | requires __adaptor_invocable<_Adaptor, _Range, const _Arg&> | |
1026 | constexpr auto | |
1027 | operator()(_Range&& __r) const | |
1028 | { return _Adaptor{}(std::forward<_Range>(__r), _M_arg); } | |
1029 | ||
1030 | static constexpr bool _S_has_simple_call_op = true; | |
1031 | }; | |
1032 | ||
a25321ca PP |
1033 | template<typename _Lhs, typename _Rhs, typename _Range> |
1034 | concept __pipe_invocable | |
1035 | = requires { std::declval<_Rhs>()(std::declval<_Lhs>()(std::declval<_Range>())); }; | |
cba9ef06 | 1036 | |
a25321ca PP |
1037 | // A range adaptor closure that represents composition of the range |
1038 | // adaptor closures _Lhs and _Rhs. | |
1039 | template<typename _Lhs, typename _Rhs> | |
1040 | struct _Pipe : _RangeAdaptorClosure | |
1041 | { | |
1042 | [[no_unique_address]] _Lhs _M_lhs; | |
1043 | [[no_unique_address]] _Rhs _M_rhs; | |
37f33df7 | 1044 | |
a25321ca PP |
1045 | constexpr |
1046 | _Pipe(_Lhs __lhs, _Rhs __rhs) | |
1047 | : _M_lhs(std::move(__lhs)), _M_rhs(std::move(__rhs)) | |
1048 | { } | |
cba9ef06 | 1049 | |
a25321ca PP |
1050 | // Invoke _M_rhs(_M_lhs(__r)) according to the value category of this |
1051 | // range adaptor closure object. | |
1052 | template<typename _Range> | |
1053 | requires __pipe_invocable<const _Lhs&, const _Rhs&, _Range> | |
1054 | constexpr auto | |
1055 | operator()(_Range&& __r) const & | |
1056 | { return _M_rhs(_M_lhs(std::forward<_Range>(__r))); } | |
1057 | ||
1058 | template<typename _Range> | |
1059 | requires __pipe_invocable<_Lhs, _Rhs, _Range> | |
1060 | constexpr auto | |
1061 | operator()(_Range&& __r) && | |
1062 | { return std::move(_M_rhs)(std::move(_M_lhs)(std::forward<_Range>(__r))); } | |
1063 | ||
1064 | template<typename _Range> | |
1065 | constexpr auto | |
1066 | operator()(_Range&& __r) const && = delete; | |
1067 | }; | |
57ed620e PP |
1068 | |
1069 | // A partial specialization of the above primary template for the case where | |
1070 | // both adaptor operands have a simple operator(). This in turn lets us | |
1071 | // implement composition using a single simple operator(), which makes | |
1072 | // overload resolution failure diagnostics more concise. | |
1073 | template<typename _Lhs, typename _Rhs> | |
1074 | requires __closure_has_simple_call_op<_Lhs> | |
1075 | && __closure_has_simple_call_op<_Rhs> | |
1076 | struct _Pipe<_Lhs, _Rhs> : _RangeAdaptorClosure | |
1077 | { | |
1078 | [[no_unique_address]] _Lhs _M_lhs; | |
1079 | [[no_unique_address]] _Rhs _M_rhs; | |
1080 | ||
1081 | constexpr | |
1082 | _Pipe(_Lhs __lhs, _Rhs __rhs) | |
1083 | : _M_lhs(std::move(__lhs)), _M_rhs(std::move(__rhs)) | |
1084 | { } | |
1085 | ||
1086 | template<typename _Range> | |
1087 | requires __pipe_invocable<const _Lhs&, const _Rhs&, _Range> | |
1088 | constexpr auto | |
1089 | operator()(_Range&& __r) const | |
1090 | { return _M_rhs(_M_lhs(std::forward<_Range>(__r))); } | |
1091 | ||
1092 | static constexpr bool _S_has_simple_call_op = true; | |
1093 | }; | |
a25321ca | 1094 | } // namespace views::__adaptor |
cba9ef06 PP |
1095 | |
1096 | template<range _Range> requires is_object_v<_Range> | |
1097 | class ref_view : public view_interface<ref_view<_Range>> | |
1098 | { | |
1099 | private: | |
4b4f5666 | 1100 | _Range* _M_r; |
cba9ef06 PP |
1101 | |
1102 | static void _S_fun(_Range&); // not defined | |
1103 | static void _S_fun(_Range&&) = delete; | |
1104 | ||
1105 | public: | |
c09cabb2 | 1106 | template<__detail::__different_from<ref_view> _Tp> |
cba9ef06 PP |
1107 | requires convertible_to<_Tp, _Range&> |
1108 | && requires { _S_fun(declval<_Tp>()); } | |
1109 | constexpr | |
1110 | ref_view(_Tp&& __t) | |
9245b0e8 | 1111 | noexcept(noexcept(static_cast<_Range&>(std::declval<_Tp>()))) |
cba9ef06 PP |
1112 | : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) |
1113 | { } | |
1114 | ||
1115 | constexpr _Range& | |
1116 | base() const | |
1117 | { return *_M_r; } | |
1118 | ||
1119 | constexpr iterator_t<_Range> | |
1120 | begin() const | |
1121 | { return ranges::begin(*_M_r); } | |
1122 | ||
1123 | constexpr sentinel_t<_Range> | |
1124 | end() const | |
1125 | { return ranges::end(*_M_r); } | |
1126 | ||
1127 | constexpr bool | |
1128 | empty() const requires requires { ranges::empty(*_M_r); } | |
1129 | { return ranges::empty(*_M_r); } | |
1130 | ||
1131 | constexpr auto | |
1132 | size() const requires sized_range<_Range> | |
1133 | { return ranges::size(*_M_r); } | |
1134 | ||
1135 | constexpr auto | |
1136 | data() const requires contiguous_range<_Range> | |
1137 | { return ranges::data(*_M_r); } | |
1138 | }; | |
1139 | ||
1140 | template<typename _Range> | |
1141 | ref_view(_Range&) -> ref_view<_Range>; | |
1142 | ||
1143 | template<typename _Tp> | |
15411a64 | 1144 | inline constexpr bool enable_borrowed_range<ref_view<_Tp>> = true; |
cba9ef06 PP |
1145 | |
1146 | namespace views | |
1147 | { | |
a25321ca PP |
1148 | namespace __detail |
1149 | { | |
1150 | template<typename _Range> | |
1151 | concept __can_ref_view = requires { ref_view{std::declval<_Range>()}; }; | |
1152 | ||
1153 | template<typename _Range> | |
1154 | concept __can_subrange = requires { subrange{std::declval<_Range>()}; }; | |
1155 | } // namespace __detail | |
1156 | ||
1157 | struct _All : __adaptor::_RangeAdaptorClosure | |
1158 | { | |
9245b0e8 JW |
1159 | template<typename _Range> |
1160 | static constexpr bool | |
1161 | _S_noexcept() | |
1162 | { | |
1163 | if constexpr (view<decay_t<_Range>>) | |
1164 | return is_nothrow_constructible_v<decay_t<_Range>, _Range>; | |
1165 | else if constexpr (__detail::__can_ref_view<_Range>) | |
1166 | return true; | |
1167 | else | |
1168 | return noexcept(subrange{std::declval<_Range>()}); | |
1169 | } | |
1170 | ||
a25321ca PP |
1171 | template<viewable_range _Range> |
1172 | requires view<decay_t<_Range>> | |
1173 | || __detail::__can_ref_view<_Range> | |
1174 | || __detail::__can_subrange<_Range> | |
1175 | constexpr auto | |
c8b024fa | 1176 | operator() [[nodiscard]] (_Range&& __r) const |
9245b0e8 | 1177 | noexcept(_S_noexcept<_Range>()) |
a25321ca PP |
1178 | { |
1179 | if constexpr (view<decay_t<_Range>>) | |
1180 | return std::forward<_Range>(__r); | |
1181 | else if constexpr (__detail::__can_ref_view<_Range>) | |
1182 | return ref_view{std::forward<_Range>(__r)}; | |
1183 | else | |
1184 | return subrange{std::forward<_Range>(__r)}; | |
1185 | } | |
57ed620e PP |
1186 | |
1187 | static constexpr bool _S_has_simple_call_op = true; | |
a25321ca PP |
1188 | }; |
1189 | ||
1190 | inline constexpr _All all; | |
cba9ef06 | 1191 | |
aca60ecf JW |
1192 | template<viewable_range _Range> |
1193 | using all_t = decltype(all(std::declval<_Range>())); | |
aca60ecf | 1194 | } // namespace views |
cba9ef06 | 1195 | |
a1535015 PP |
1196 | namespace __detail |
1197 | { | |
46ed811b PP |
1198 | template<typename _Tp> |
1199 | struct __non_propagating_cache | |
1200 | { | |
1201 | // When _Tp is not an object type (e.g. is a reference type), we make | |
1202 | // __non_propagating_cache<_Tp> empty rather than ill-formed so that | |
1203 | // users can easily conditionally declare data members with this type | |
1204 | // (such as join_view::_M_inner). | |
1205 | }; | |
1206 | ||
1207 | template<typename _Tp> | |
1208 | requires is_object_v<_Tp> | |
2c564e81 | 1209 | struct __non_propagating_cache<_Tp> |
82b2e4f8 | 1210 | : protected _Optional_base<_Tp> |
46ed811b PP |
1211 | { |
1212 | __non_propagating_cache() = default; | |
1213 | ||
1214 | constexpr | |
1215 | __non_propagating_cache(const __non_propagating_cache&) noexcept | |
1216 | { } | |
1217 | ||
1218 | constexpr | |
1219 | __non_propagating_cache(__non_propagating_cache&& __other) noexcept | |
1220 | { __other._M_reset(); } | |
1221 | ||
1222 | constexpr __non_propagating_cache& | |
1223 | operator=(const __non_propagating_cache& __other) noexcept | |
1224 | { | |
1225 | if (std::__addressof(__other) != this) | |
1226 | this->_M_reset(); | |
1227 | return *this; | |
1228 | } | |
1229 | ||
1230 | constexpr __non_propagating_cache& | |
1231 | operator=(__non_propagating_cache&& __other) noexcept | |
1232 | { | |
1233 | this->_M_reset(); | |
1234 | __other._M_reset(); | |
1235 | return *this; | |
1236 | } | |
1237 | ||
4b4f5666 PP |
1238 | constexpr __non_propagating_cache& |
1239 | operator=(_Tp __val) | |
1240 | { | |
1241 | this->_M_reset(); | |
82b2e4f8 | 1242 | this->_M_payload._M_construct(std::move(__val)); |
4b4f5666 PP |
1243 | return *this; |
1244 | } | |
1245 | ||
69d80f0f PP |
1246 | constexpr explicit |
1247 | operator bool() const noexcept | |
1248 | { return this->_M_is_engaged(); } | |
1249 | ||
46ed811b PP |
1250 | constexpr _Tp& |
1251 | operator*() noexcept | |
82b2e4f8 | 1252 | { return this->_M_get(); } |
46ed811b PP |
1253 | |
1254 | constexpr const _Tp& | |
1255 | operator*() const noexcept | |
82b2e4f8 | 1256 | { return this->_M_get(); } |
46ed811b PP |
1257 | |
1258 | template<typename _Iter> | |
2c564e81 | 1259 | constexpr _Tp& |
46ed811b PP |
1260 | _M_emplace_deref(const _Iter& __i) |
1261 | { | |
1262 | this->_M_reset(); | |
82b2e4f8 JW |
1263 | auto __f = [] (auto& __x) { return *__x; }; |
1264 | this->_M_payload._M_apply(_Optional_func{__f}, __i); | |
1265 | return this->_M_get(); | |
46ed811b PP |
1266 | } |
1267 | }; | |
1268 | ||
a1535015 PP |
1269 | template<range _Range> |
1270 | struct _CachedPosition | |
1271 | { | |
1272 | constexpr bool | |
1273 | _M_has_value() const | |
1274 | { return false; } | |
1275 | ||
1276 | constexpr iterator_t<_Range> | |
1277 | _M_get(const _Range&) const | |
1278 | { | |
1279 | __glibcxx_assert(false); | |
1af937eb | 1280 | __builtin_unreachable(); |
a1535015 PP |
1281 | } |
1282 | ||
1283 | constexpr void | |
1284 | _M_set(const _Range&, const iterator_t<_Range>&) const | |
1285 | { } | |
1286 | }; | |
1287 | ||
1288 | template<forward_range _Range> | |
1289 | struct _CachedPosition<_Range> | |
46ed811b | 1290 | : protected __non_propagating_cache<iterator_t<_Range>> |
a1535015 | 1291 | { |
a1535015 PP |
1292 | constexpr bool |
1293 | _M_has_value() const | |
46ed811b | 1294 | { return this->_M_is_engaged(); } |
a1535015 PP |
1295 | |
1296 | constexpr iterator_t<_Range> | |
1297 | _M_get(const _Range&) const | |
1298 | { | |
1299 | __glibcxx_assert(_M_has_value()); | |
46ed811b | 1300 | return **this; |
a1535015 PP |
1301 | } |
1302 | ||
1303 | constexpr void | |
1304 | _M_set(const _Range&, const iterator_t<_Range>& __it) | |
1305 | { | |
1306 | __glibcxx_assert(!_M_has_value()); | |
46ed811b PP |
1307 | std::construct_at(std::__addressof(this->_M_payload._M_payload), |
1308 | in_place, __it); | |
1309 | this->_M_payload._M_engaged = true; | |
a1535015 PP |
1310 | } |
1311 | }; | |
1312 | ||
1313 | template<random_access_range _Range> | |
1314 | requires (sizeof(range_difference_t<_Range>) | |
1315 | <= sizeof(iterator_t<_Range>)) | |
1316 | struct _CachedPosition<_Range> | |
1317 | { | |
1318 | private: | |
1319 | range_difference_t<_Range> _M_offset = -1; | |
1320 | ||
1321 | public: | |
46ed811b PP |
1322 | _CachedPosition() = default; |
1323 | ||
1324 | constexpr | |
1325 | _CachedPosition(const _CachedPosition&) = default; | |
1326 | ||
1327 | constexpr | |
1328 | _CachedPosition(_CachedPosition&& __other) noexcept | |
1329 | { *this = std::move(__other); } | |
1330 | ||
1331 | constexpr _CachedPosition& | |
1332 | operator=(const _CachedPosition&) = default; | |
1333 | ||
1334 | constexpr _CachedPosition& | |
1335 | operator=(_CachedPosition&& __other) noexcept | |
1336 | { | |
1337 | // Propagate the cached offset, but invalidate the source. | |
1338 | _M_offset = __other._M_offset; | |
1339 | __other._M_offset = -1; | |
1340 | return *this; | |
1341 | } | |
1342 | ||
a1535015 PP |
1343 | constexpr bool |
1344 | _M_has_value() const | |
1345 | { return _M_offset >= 0; } | |
1346 | ||
1347 | constexpr iterator_t<_Range> | |
1348 | _M_get(_Range& __r) const | |
1349 | { | |
1350 | __glibcxx_assert(_M_has_value()); | |
1351 | return ranges::begin(__r) + _M_offset; | |
1352 | } | |
1353 | ||
1354 | constexpr void | |
1355 | _M_set(_Range& __r, const iterator_t<_Range>& __it) | |
1356 | { | |
1357 | __glibcxx_assert(!_M_has_value()); | |
1358 | _M_offset = __it - ranges::begin(__r); | |
1359 | } | |
1360 | }; | |
902b40c7 PP |
1361 | } // namespace __detail |
1362 | ||
1363 | namespace __detail | |
1364 | { | |
1365 | template<typename _Base> | |
1366 | struct __filter_view_iter_cat | |
1367 | { }; | |
a1535015 | 1368 | |
902b40c7 PP |
1369 | template<forward_range _Base> |
1370 | struct __filter_view_iter_cat<_Base> | |
1371 | { | |
1372 | private: | |
1373 | static auto | |
1374 | _S_iter_cat() | |
1375 | { | |
1376 | using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; | |
1377 | if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) | |
1378 | return bidirectional_iterator_tag{}; | |
1379 | else if constexpr (derived_from<_Cat, forward_iterator_tag>) | |
1380 | return forward_iterator_tag{}; | |
1381 | else | |
1382 | return _Cat{}; | |
1383 | } | |
1384 | public: | |
1385 | using iterator_category = decltype(_S_iter_cat()); | |
1386 | }; | |
a1535015 PP |
1387 | } // namespace __detail |
1388 | ||
cba9ef06 PP |
1389 | template<input_range _Vp, |
1390 | indirect_unary_predicate<iterator_t<_Vp>> _Pred> | |
1391 | requires view<_Vp> && is_object_v<_Pred> | |
1392 | class filter_view : public view_interface<filter_view<_Vp, _Pred>> | |
1393 | { | |
1394 | private: | |
1395 | struct _Sentinel; | |
1396 | ||
902b40c7 | 1397 | struct _Iterator : __detail::__filter_view_iter_cat<_Vp> |
cba9ef06 PP |
1398 | { |
1399 | private: | |
1400 | static constexpr auto | |
1401 | _S_iter_concept() | |
1402 | { | |
1403 | if constexpr (bidirectional_range<_Vp>) | |
1404 | return bidirectional_iterator_tag{}; | |
1405 | else if constexpr (forward_range<_Vp>) | |
1406 | return forward_iterator_tag{}; | |
1407 | else | |
1408 | return input_iterator_tag{}; | |
1409 | } | |
1410 | ||
cba9ef06 PP |
1411 | friend filter_view; |
1412 | ||
a5b213dd JW |
1413 | using _Vp_iter = iterator_t<_Vp>; |
1414 | ||
1415 | _Vp_iter _M_current = _Vp_iter(); | |
cba9ef06 PP |
1416 | filter_view* _M_parent = nullptr; |
1417 | ||
1418 | public: | |
1419 | using iterator_concept = decltype(_S_iter_concept()); | |
902b40c7 | 1420 | // iterator_category defined in __filter_view_iter_cat |
cba9ef06 PP |
1421 | using value_type = range_value_t<_Vp>; |
1422 | using difference_type = range_difference_t<_Vp>; | |
1423 | ||
4b4f5666 | 1424 | _Iterator() requires default_initializable<_Vp_iter> = default; |
cba9ef06 PP |
1425 | |
1426 | constexpr | |
afb8da7f | 1427 | _Iterator(filter_view* __parent, _Vp_iter __current) |
cba9ef06 | 1428 | : _M_current(std::move(__current)), |
afb8da7f | 1429 | _M_parent(__parent) |
cba9ef06 PP |
1430 | { } |
1431 | ||
eb1aa9ad PP |
1432 | constexpr const _Vp_iter& |
1433 | base() const & noexcept | |
cba9ef06 PP |
1434 | { return _M_current; } |
1435 | ||
a5b213dd | 1436 | constexpr _Vp_iter |
cba9ef06 PP |
1437 | base() && |
1438 | { return std::move(_M_current); } | |
1439 | ||
1440 | constexpr range_reference_t<_Vp> | |
1441 | operator*() const | |
1442 | { return *_M_current; } | |
1443 | ||
a5b213dd | 1444 | constexpr _Vp_iter |
cba9ef06 | 1445 | operator->() const |
a5b213dd JW |
1446 | requires __detail::__has_arrow<_Vp_iter> |
1447 | && copyable<_Vp_iter> | |
cba9ef06 PP |
1448 | { return _M_current; } |
1449 | ||
1450 | constexpr _Iterator& | |
1451 | operator++() | |
1452 | { | |
2786064d PP |
1453 | _M_current = ranges::find_if(std::move(++_M_current), |
1454 | ranges::end(_M_parent->_M_base), | |
1455 | std::ref(*_M_parent->_M_pred)); | |
cba9ef06 PP |
1456 | return *this; |
1457 | } | |
1458 | ||
1459 | constexpr void | |
1460 | operator++(int) | |
1461 | { ++*this; } | |
1462 | ||
1463 | constexpr _Iterator | |
1464 | operator++(int) requires forward_range<_Vp> | |
1465 | { | |
1466 | auto __tmp = *this; | |
1467 | ++*this; | |
1468 | return __tmp; | |
1469 | } | |
1470 | ||
1471 | constexpr _Iterator& | |
1472 | operator--() requires bidirectional_range<_Vp> | |
1473 | { | |
1474 | do | |
1475 | --_M_current; | |
1476 | while (!std::__invoke(*_M_parent->_M_pred, *_M_current)); | |
1477 | return *this; | |
1478 | } | |
1479 | ||
1480 | constexpr _Iterator | |
1481 | operator--(int) requires bidirectional_range<_Vp> | |
1482 | { | |
1483 | auto __tmp = *this; | |
1484 | --*this; | |
1485 | return __tmp; | |
1486 | } | |
1487 | ||
1488 | friend constexpr bool | |
1489 | operator==(const _Iterator& __x, const _Iterator& __y) | |
a5b213dd | 1490 | requires equality_comparable<_Vp_iter> |
cba9ef06 PP |
1491 | { return __x._M_current == __y._M_current; } |
1492 | ||
1493 | friend constexpr range_rvalue_reference_t<_Vp> | |
1494 | iter_move(const _Iterator& __i) | |
1495 | noexcept(noexcept(ranges::iter_move(__i._M_current))) | |
1496 | { return ranges::iter_move(__i._M_current); } | |
1497 | ||
1498 | friend constexpr void | |
1499 | iter_swap(const _Iterator& __x, const _Iterator& __y) | |
1500 | noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) | |
a5b213dd | 1501 | requires indirectly_swappable<_Vp_iter> |
cba9ef06 PP |
1502 | { ranges::iter_swap(__x._M_current, __y._M_current); } |
1503 | }; | |
1504 | ||
1505 | struct _Sentinel | |
1506 | { | |
1507 | private: | |
1508 | sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); | |
1509 | ||
1510 | constexpr bool | |
1511 | __equal(const _Iterator& __i) const | |
1512 | { return __i._M_current == _M_end; } | |
1513 | ||
1514 | public: | |
1515 | _Sentinel() = default; | |
1516 | ||
1517 | constexpr explicit | |
afb8da7f PP |
1518 | _Sentinel(filter_view* __parent) |
1519 | : _M_end(ranges::end(__parent->_M_base)) | |
cba9ef06 PP |
1520 | { } |
1521 | ||
1522 | constexpr sentinel_t<_Vp> | |
1523 | base() const | |
1524 | { return _M_end; } | |
1525 | ||
1526 | friend constexpr bool | |
1527 | operator==(const _Iterator& __x, const _Sentinel& __y) | |
1528 | { return __y.__equal(__x); } | |
1529 | }; | |
1530 | ||
53b1c382 | 1531 | _Vp _M_base = _Vp(); |
42907ca9 | 1532 | [[no_unique_address]] __detail::__box<_Pred> _M_pred; |
a1535015 | 1533 | [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; |
cba9ef06 PP |
1534 | |
1535 | public: | |
4b4f5666 PP |
1536 | filter_view() requires (default_initializable<_Vp> |
1537 | && default_initializable<_Pred>) | |
1538 | = default; | |
cba9ef06 PP |
1539 | |
1540 | constexpr | |
1541 | filter_view(_Vp __base, _Pred __pred) | |
53b1c382 | 1542 | : _M_base(std::move(__base)), _M_pred(std::move(__pred)) |
cba9ef06 PP |
1543 | { } |
1544 | ||
cba9ef06 PP |
1545 | constexpr _Vp |
1546 | base() const& requires copy_constructible<_Vp> | |
1547 | { return _M_base; } | |
1548 | ||
1549 | constexpr _Vp | |
1550 | base() && | |
1551 | { return std::move(_M_base); } | |
1552 | ||
242b4fb7 PP |
1553 | constexpr const _Pred& |
1554 | pred() const | |
1555 | { return *_M_pred; } | |
1556 | ||
cba9ef06 PP |
1557 | constexpr _Iterator |
1558 | begin() | |
1559 | { | |
a1535015 | 1560 | if (_M_cached_begin._M_has_value()) |
afb8da7f | 1561 | return {this, _M_cached_begin._M_get(_M_base)}; |
a1535015 | 1562 | |
cba9ef06 | 1563 | __glibcxx_assert(_M_pred.has_value()); |
2786064d PP |
1564 | auto __it = ranges::find_if(ranges::begin(_M_base), |
1565 | ranges::end(_M_base), | |
1566 | std::ref(*_M_pred)); | |
a1535015 | 1567 | _M_cached_begin._M_set(_M_base, __it); |
afb8da7f | 1568 | return {this, std::move(__it)}; |
cba9ef06 PP |
1569 | } |
1570 | ||
1571 | constexpr auto | |
1572 | end() | |
1573 | { | |
1574 | if constexpr (common_range<_Vp>) | |
afb8da7f | 1575 | return _Iterator{this, ranges::end(_M_base)}; |
cba9ef06 | 1576 | else |
afb8da7f | 1577 | return _Sentinel{this}; |
cba9ef06 PP |
1578 | } |
1579 | }; | |
1580 | ||
1581 | template<typename _Range, typename _Pred> | |
aca60ecf | 1582 | filter_view(_Range&&, _Pred) -> filter_view<views::all_t<_Range>, _Pred>; |
cba9ef06 PP |
1583 | |
1584 | namespace views | |
1585 | { | |
a25321ca PP |
1586 | namespace __detail |
1587 | { | |
1588 | template<typename _Range, typename _Pred> | |
1589 | concept __can_filter_view | |
6e00d9bb | 1590 | = requires { filter_view(std::declval<_Range>(), std::declval<_Pred>()); }; |
a25321ca PP |
1591 | } // namespace __detail |
1592 | ||
1593 | struct _Filter : __adaptor::_RangeAdaptor<_Filter> | |
1594 | { | |
1595 | template<viewable_range _Range, typename _Pred> | |
1596 | requires __detail::__can_filter_view<_Range, _Pred> | |
1597 | constexpr auto | |
c8b024fa | 1598 | operator() [[nodiscard]] (_Range&& __r, _Pred&& __p) const |
a25321ca | 1599 | { |
6e00d9bb | 1600 | return filter_view(std::forward<_Range>(__r), std::forward<_Pred>(__p)); |
a25321ca PP |
1601 | } |
1602 | ||
1603 | using _RangeAdaptor<_Filter>::operator(); | |
1604 | static constexpr int _S_arity = 2; | |
57ed620e | 1605 | static constexpr bool _S_has_simple_extra_args = true; |
a25321ca PP |
1606 | }; |
1607 | ||
1608 | inline constexpr _Filter filter; | |
cba9ef06 PP |
1609 | } // namespace views |
1610 | ||
1611 | template<input_range _Vp, copy_constructible _Fp> | |
1612 | requires view<_Vp> && is_object_v<_Fp> | |
1613 | && regular_invocable<_Fp&, range_reference_t<_Vp>> | |
ec15da7c PP |
1614 | && std::__detail::__can_reference<invoke_result_t<_Fp&, |
1615 | range_reference_t<_Vp>>> | |
cba9ef06 PP |
1616 | class transform_view : public view_interface<transform_view<_Vp, _Fp>> |
1617 | { | |
1618 | private: | |
1619 | template<bool _Const> | |
902b40c7 | 1620 | using _Base = __detail::__maybe_const_t<_Const, _Vp>; |
cba9ef06 PP |
1621 | |
1622 | template<bool _Const> | |
902b40c7 PP |
1623 | struct __iter_cat |
1624 | { }; | |
1625 | ||
1626 | template<bool _Const> | |
1627 | requires forward_range<_Base<_Const>> | |
1628 | struct __iter_cat<_Const> | |
cba9ef06 PP |
1629 | { |
1630 | private: | |
902b40c7 | 1631 | static auto |
cba9ef06 PP |
1632 | _S_iter_cat() |
1633 | { | |
902b40c7 | 1634 | using _Base = transform_view::_Base<_Const>; |
510bd1c1 PP |
1635 | using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>; |
1636 | if constexpr (is_lvalue_reference_v<_Res>) | |
1637 | { | |
1638 | using _Cat | |
902b40c7 | 1639 | = typename iterator_traits<iterator_t<_Base>>::iterator_category; |
510bd1c1 PP |
1640 | if constexpr (derived_from<_Cat, contiguous_iterator_tag>) |
1641 | return random_access_iterator_tag{}; | |
1642 | else | |
1643 | return _Cat{}; | |
1644 | } | |
cba9ef06 | 1645 | else |
510bd1c1 | 1646 | return input_iterator_tag{}; |
cba9ef06 | 1647 | } |
902b40c7 PP |
1648 | public: |
1649 | using iterator_category = decltype(_S_iter_cat()); | |
1650 | }; | |
1651 | ||
1652 | template<bool _Const> | |
1653 | struct _Sentinel; | |
1654 | ||
1655 | template<bool _Const> | |
1656 | struct _Iterator : __iter_cat<_Const> | |
1657 | { | |
1658 | private: | |
1659 | using _Parent = __detail::__maybe_const_t<_Const, transform_view>; | |
1660 | using _Base = transform_view::_Base<_Const>; | |
1661 | ||
1662 | static auto | |
1663 | _S_iter_concept() | |
1664 | { | |
bc046a60 | 1665 | if constexpr (random_access_range<_Base>) |
902b40c7 | 1666 | return random_access_iterator_tag{}; |
bc046a60 | 1667 | else if constexpr (bidirectional_range<_Base>) |
902b40c7 | 1668 | return bidirectional_iterator_tag{}; |
bc046a60 | 1669 | else if constexpr (forward_range<_Base>) |
902b40c7 PP |
1670 | return forward_iterator_tag{}; |
1671 | else | |
1672 | return input_iterator_tag{}; | |
1673 | } | |
cba9ef06 | 1674 | |
a5b213dd JW |
1675 | using _Base_iter = iterator_t<_Base>; |
1676 | ||
1677 | _Base_iter _M_current = _Base_iter(); | |
cba9ef06 PP |
1678 | _Parent* _M_parent = nullptr; |
1679 | ||
1680 | public: | |
1681 | using iterator_concept = decltype(_S_iter_concept()); | |
902b40c7 | 1682 | // iterator_category defined in __transform_view_iter_cat |
cba9ef06 PP |
1683 | using value_type |
1684 | = remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>; | |
1685 | using difference_type = range_difference_t<_Base>; | |
1686 | ||
4b4f5666 | 1687 | _Iterator() requires default_initializable<_Base_iter> = default; |
cba9ef06 PP |
1688 | |
1689 | constexpr | |
afb8da7f | 1690 | _Iterator(_Parent* __parent, _Base_iter __current) |
cba9ef06 | 1691 | : _M_current(std::move(__current)), |
afb8da7f | 1692 | _M_parent(__parent) |
cba9ef06 PP |
1693 | { } |
1694 | ||
1695 | constexpr | |
1696 | _Iterator(_Iterator<!_Const> __i) | |
1697 | requires _Const | |
a5b213dd | 1698 | && convertible_to<iterator_t<_Vp>, _Base_iter> |
cba9ef06 PP |
1699 | : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent) |
1700 | { } | |
1701 | ||
eb1aa9ad PP |
1702 | constexpr const _Base_iter& |
1703 | base() const & noexcept | |
cba9ef06 PP |
1704 | { return _M_current; } |
1705 | ||
a5b213dd | 1706 | constexpr _Base_iter |
cba9ef06 PP |
1707 | base() && |
1708 | { return std::move(_M_current); } | |
1709 | ||
1710 | constexpr decltype(auto) | |
1711 | operator*() const | |
cf0c3a45 | 1712 | noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current))) |
cba9ef06 PP |
1713 | { return std::__invoke(*_M_parent->_M_fun, *_M_current); } |
1714 | ||
1715 | constexpr _Iterator& | |
1716 | operator++() | |
1717 | { | |
1718 | ++_M_current; | |
1719 | return *this; | |
1720 | } | |
1721 | ||
1722 | constexpr void | |
1723 | operator++(int) | |
1724 | { ++_M_current; } | |
1725 | ||
1726 | constexpr _Iterator | |
1727 | operator++(int) requires forward_range<_Base> | |
1728 | { | |
1729 | auto __tmp = *this; | |
1730 | ++*this; | |
1731 | return __tmp; | |
1732 | } | |
1733 | ||
1734 | constexpr _Iterator& | |
1735 | operator--() requires bidirectional_range<_Base> | |
1736 | { | |
1737 | --_M_current; | |
1738 | return *this; | |
1739 | } | |
1740 | ||
1741 | constexpr _Iterator | |
1742 | operator--(int) requires bidirectional_range<_Base> | |
1743 | { | |
1744 | auto __tmp = *this; | |
1745 | --*this; | |
1746 | return __tmp; | |
1747 | } | |
1748 | ||
1749 | constexpr _Iterator& | |
1750 | operator+=(difference_type __n) requires random_access_range<_Base> | |
1751 | { | |
1752 | _M_current += __n; | |
1753 | return *this; | |
1754 | } | |
1755 | ||
1756 | constexpr _Iterator& | |
1757 | operator-=(difference_type __n) requires random_access_range<_Base> | |
1758 | { | |
1759 | _M_current -= __n; | |
1760 | return *this; | |
1761 | } | |
1762 | ||
1763 | constexpr decltype(auto) | |
1764 | operator[](difference_type __n) const | |
1765 | requires random_access_range<_Base> | |
1766 | { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); } | |
1767 | ||
1768 | friend constexpr bool | |
1769 | operator==(const _Iterator& __x, const _Iterator& __y) | |
a5b213dd | 1770 | requires equality_comparable<_Base_iter> |
cba9ef06 PP |
1771 | { return __x._M_current == __y._M_current; } |
1772 | ||
1773 | friend constexpr bool | |
1774 | operator<(const _Iterator& __x, const _Iterator& __y) | |
1775 | requires random_access_range<_Base> | |
1776 | { return __x._M_current < __y._M_current; } | |
1777 | ||
1778 | friend constexpr bool | |
1779 | operator>(const _Iterator& __x, const _Iterator& __y) | |
1780 | requires random_access_range<_Base> | |
1781 | { return __y < __x; } | |
1782 | ||
1783 | friend constexpr bool | |
1784 | operator<=(const _Iterator& __x, const _Iterator& __y) | |
1785 | requires random_access_range<_Base> | |
1786 | { return !(__y < __x); } | |
1787 | ||
1788 | friend constexpr bool | |
1789 | operator>=(const _Iterator& __x, const _Iterator& __y) | |
1790 | requires random_access_range<_Base> | |
1791 | { return !(__x < __y); } | |
1792 | ||
1793 | #ifdef __cpp_lib_three_way_comparison | |
1794 | friend constexpr auto | |
1795 | operator<=>(const _Iterator& __x, const _Iterator& __y) | |
1796 | requires random_access_range<_Base> | |
a5b213dd | 1797 | && three_way_comparable<_Base_iter> |
cba9ef06 PP |
1798 | { return __x._M_current <=> __y._M_current; } |
1799 | #endif | |
1800 | ||
1801 | friend constexpr _Iterator | |
1802 | operator+(_Iterator __i, difference_type __n) | |
1803 | requires random_access_range<_Base> | |
afb8da7f | 1804 | { return {__i._M_parent, __i._M_current + __n}; } |
cba9ef06 PP |
1805 | |
1806 | friend constexpr _Iterator | |
1807 | operator+(difference_type __n, _Iterator __i) | |
1808 | requires random_access_range<_Base> | |
afb8da7f | 1809 | { return {__i._M_parent, __i._M_current + __n}; } |
cba9ef06 PP |
1810 | |
1811 | friend constexpr _Iterator | |
1812 | operator-(_Iterator __i, difference_type __n) | |
1813 | requires random_access_range<_Base> | |
afb8da7f | 1814 | { return {__i._M_parent, __i._M_current - __n}; } |
cba9ef06 | 1815 | |
2ec58cfc JW |
1816 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1817 | // 3483. transform_view::iterator's difference is overconstrained | |
cba9ef06 PP |
1818 | friend constexpr difference_type |
1819 | operator-(const _Iterator& __x, const _Iterator& __y) | |
2ec58cfc | 1820 | requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> |
cba9ef06 PP |
1821 | { return __x._M_current - __y._M_current; } |
1822 | ||
1823 | friend constexpr decltype(auto) | |
cf0c3a45 JW |
1824 | iter_move(const _Iterator& __i) noexcept(noexcept(*__i)) |
1825 | { | |
1826 | if constexpr (is_lvalue_reference_v<decltype(*__i)>) | |
1827 | return std::move(*__i); | |
1828 | else | |
1829 | return *__i; | |
1830 | } | |
cba9ef06 | 1831 | |
ba49e9eb | 1832 | friend _Iterator<!_Const>; |
6c2582c0 | 1833 | template<bool> friend struct _Sentinel; |
cba9ef06 PP |
1834 | }; |
1835 | ||
1836 | template<bool _Const> | |
1837 | struct _Sentinel | |
1838 | { | |
1839 | private: | |
8017d95c | 1840 | using _Parent = __detail::__maybe_const_t<_Const, transform_view>; |
902b40c7 | 1841 | using _Base = transform_view::_Base<_Const>; |
cba9ef06 | 1842 | |
6c2582c0 | 1843 | template<bool _Const2> |
3ae0cd94 | 1844 | constexpr auto |
6c2582c0 JW |
1845 | __distance_from(const _Iterator<_Const2>& __i) const |
1846 | { return _M_end - __i._M_current; } | |
cba9ef06 | 1847 | |
6c2582c0 JW |
1848 | template<bool _Const2> |
1849 | constexpr bool | |
1850 | __equal(const _Iterator<_Const2>& __i) const | |
1851 | { return __i._M_current == _M_end; } | |
cba9ef06 PP |
1852 | |
1853 | sentinel_t<_Base> _M_end = sentinel_t<_Base>(); | |
1854 | ||
1855 | public: | |
1856 | _Sentinel() = default; | |
1857 | ||
1858 | constexpr explicit | |
1859 | _Sentinel(sentinel_t<_Base> __end) | |
1860 | : _M_end(__end) | |
1861 | { } | |
1862 | ||
1863 | constexpr | |
1864 | _Sentinel(_Sentinel<!_Const> __i) | |
1865 | requires _Const | |
1866 | && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> | |
1867 | : _M_end(std::move(__i._M_end)) | |
1868 | { } | |
1869 | ||
1870 | constexpr sentinel_t<_Base> | |
1871 | base() const | |
1872 | { return _M_end; } | |
1873 | ||
6c2582c0 JW |
1874 | template<bool _Const2> |
1875 | requires sentinel_for<sentinel_t<_Base>, | |
1876 | iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> | |
1877 | friend constexpr bool | |
1878 | operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) | |
1879 | { return __y.__equal(__x); } | |
1880 | ||
3ae0cd94 PP |
1881 | template<bool _Const2, |
1882 | typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>> | |
1883 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>> | |
1884 | friend constexpr range_difference_t<_Base2> | |
6c2582c0 JW |
1885 | operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) |
1886 | { return -__y.__distance_from(__x); } | |
1887 | ||
3ae0cd94 PP |
1888 | template<bool _Const2, |
1889 | typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>> | |
1890 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>> | |
1891 | friend constexpr range_difference_t<_Base2> | |
6c2582c0 JW |
1892 | operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x) |
1893 | { return __y.__distance_from(__x); } | |
ba49e9eb PP |
1894 | |
1895 | friend _Sentinel<!_Const>; | |
cba9ef06 PP |
1896 | }; |
1897 | ||
361e32ee | 1898 | _Vp _M_base = _Vp(); |
53b1c382 | 1899 | [[no_unique_address]] __detail::__box<_Fp> _M_fun; |
cba9ef06 PP |
1900 | |
1901 | public: | |
4b4f5666 PP |
1902 | transform_view() requires (default_initializable<_Vp> |
1903 | && default_initializable<_Fp>) | |
1904 | = default; | |
cba9ef06 PP |
1905 | |
1906 | constexpr | |
1907 | transform_view(_Vp __base, _Fp __fun) | |
53b1c382 | 1908 | : _M_base(std::move(__base)), _M_fun(std::move(__fun)) |
cba9ef06 PP |
1909 | { } |
1910 | ||
cba9ef06 PP |
1911 | constexpr _Vp |
1912 | base() const& requires copy_constructible<_Vp> | |
1913 | { return _M_base ; } | |
1914 | ||
1915 | constexpr _Vp | |
1916 | base() && | |
1917 | { return std::move(_M_base); } | |
1918 | ||
1919 | constexpr _Iterator<false> | |
1920 | begin() | |
afb8da7f | 1921 | { return _Iterator<false>{this, ranges::begin(_M_base)}; } |
cba9ef06 PP |
1922 | |
1923 | constexpr _Iterator<true> | |
1924 | begin() const | |
1925 | requires range<const _Vp> | |
1926 | && regular_invocable<const _Fp&, range_reference_t<const _Vp>> | |
afb8da7f | 1927 | { return _Iterator<true>{this, ranges::begin(_M_base)}; } |
cba9ef06 PP |
1928 | |
1929 | constexpr _Sentinel<false> | |
1930 | end() | |
1931 | { return _Sentinel<false>{ranges::end(_M_base)}; } | |
1932 | ||
1933 | constexpr _Iterator<false> | |
1934 | end() requires common_range<_Vp> | |
afb8da7f | 1935 | { return _Iterator<false>{this, ranges::end(_M_base)}; } |
cba9ef06 PP |
1936 | |
1937 | constexpr _Sentinel<true> | |
1938 | end() const | |
1939 | requires range<const _Vp> | |
1940 | && regular_invocable<const _Fp&, range_reference_t<const _Vp>> | |
1941 | { return _Sentinel<true>{ranges::end(_M_base)}; } | |
1942 | ||
1943 | constexpr _Iterator<true> | |
1944 | end() const | |
1945 | requires common_range<const _Vp> | |
1946 | && regular_invocable<const _Fp&, range_reference_t<const _Vp>> | |
afb8da7f | 1947 | { return _Iterator<true>{this, ranges::end(_M_base)}; } |
cba9ef06 PP |
1948 | |
1949 | constexpr auto | |
1950 | size() requires sized_range<_Vp> | |
1951 | { return ranges::size(_M_base); } | |
1952 | ||
1953 | constexpr auto | |
1954 | size() const requires sized_range<const _Vp> | |
1955 | { return ranges::size(_M_base); } | |
1956 | }; | |
1957 | ||
1958 | template<typename _Range, typename _Fp> | |
aca60ecf | 1959 | transform_view(_Range&&, _Fp) -> transform_view<views::all_t<_Range>, _Fp>; |
cba9ef06 PP |
1960 | |
1961 | namespace views | |
1962 | { | |
a25321ca PP |
1963 | namespace __detail |
1964 | { | |
1965 | template<typename _Range, typename _Fp> | |
1966 | concept __can_transform_view | |
6e00d9bb | 1967 | = requires { transform_view(std::declval<_Range>(), std::declval<_Fp>()); }; |
a25321ca PP |
1968 | } // namespace __detail |
1969 | ||
1970 | struct _Transform : __adaptor::_RangeAdaptor<_Transform> | |
1971 | { | |
1972 | template<viewable_range _Range, typename _Fp> | |
1973 | requires __detail::__can_transform_view<_Range, _Fp> | |
1974 | constexpr auto | |
c8b024fa | 1975 | operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const |
a25321ca | 1976 | { |
6e00d9bb | 1977 | return transform_view(std::forward<_Range>(__r), std::forward<_Fp>(__f)); |
a25321ca PP |
1978 | } |
1979 | ||
1980 | using _RangeAdaptor<_Transform>::operator(); | |
1981 | static constexpr int _S_arity = 2; | |
57ed620e | 1982 | static constexpr bool _S_has_simple_extra_args = true; |
a25321ca PP |
1983 | }; |
1984 | ||
1985 | inline constexpr _Transform transform; | |
cba9ef06 PP |
1986 | } // namespace views |
1987 | ||
1988 | template<view _Vp> | |
1989 | class take_view : public view_interface<take_view<_Vp>> | |
1990 | { | |
1991 | private: | |
e066821b PP |
1992 | template<bool _Const> |
1993 | using _CI = counted_iterator< | |
1994 | iterator_t<__detail::__maybe_const_t<_Const, _Vp>>>; | |
1995 | ||
cba9ef06 PP |
1996 | template<bool _Const> |
1997 | struct _Sentinel | |
1998 | { | |
1999 | private: | |
8017d95c | 2000 | using _Base = __detail::__maybe_const_t<_Const, _Vp>; |
cba9ef06 PP |
2001 | sentinel_t<_Base> _M_end = sentinel_t<_Base>(); |
2002 | ||
2003 | public: | |
2004 | _Sentinel() = default; | |
2005 | ||
2006 | constexpr explicit | |
2007 | _Sentinel(sentinel_t<_Base> __end) | |
2008 | : _M_end(__end) | |
2009 | { } | |
2010 | ||
2011 | constexpr | |
2012 | _Sentinel(_Sentinel<!_Const> __s) | |
2013 | requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> | |
2014 | : _M_end(std::move(__s._M_end)) | |
2015 | { } | |
2016 | ||
2017 | constexpr sentinel_t<_Base> | |
2018 | base() const | |
2019 | { return _M_end; } | |
2020 | ||
e066821b PP |
2021 | friend constexpr bool |
2022 | operator==(const _CI<_Const>& __y, const _Sentinel& __x) | |
2023 | { return __y.count() == 0 || __y.base() == __x._M_end; } | |
2024 | ||
2025 | template<bool _OtherConst = !_Const, | |
2026 | typename _Base2 = __detail::__maybe_const_t<_OtherConst, _Vp>> | |
2027 | requires sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>> | |
2028 | friend constexpr bool | |
2029 | operator==(const _CI<_OtherConst>& __y, const _Sentinel& __x) | |
cba9ef06 | 2030 | { return __y.count() == 0 || __y.base() == __x._M_end; } |
ba49e9eb PP |
2031 | |
2032 | friend _Sentinel<!_Const>; | |
cba9ef06 PP |
2033 | }; |
2034 | ||
361e32ee | 2035 | _Vp _M_base = _Vp(); |
53b1c382 | 2036 | range_difference_t<_Vp> _M_count = 0; |
cba9ef06 PP |
2037 | |
2038 | public: | |
4b4f5666 | 2039 | take_view() requires default_initializable<_Vp> = default; |
cba9ef06 PP |
2040 | |
2041 | constexpr | |
2042 | take_view(_Vp base, range_difference_t<_Vp> __count) | |
53b1c382 | 2043 | : _M_base(std::move(base)), _M_count(std::move(__count)) |
cba9ef06 PP |
2044 | { } |
2045 | ||
cba9ef06 PP |
2046 | constexpr _Vp |
2047 | base() const& requires copy_constructible<_Vp> | |
2048 | { return _M_base; } | |
2049 | ||
2050 | constexpr _Vp | |
2051 | base() && | |
2052 | { return std::move(_M_base); } | |
2053 | ||
2054 | constexpr auto | |
2055 | begin() requires (!__detail::__simple_view<_Vp>) | |
2056 | { | |
2057 | if constexpr (sized_range<_Vp>) | |
2058 | { | |
2059 | if constexpr (random_access_range<_Vp>) | |
2060 | return ranges::begin(_M_base); | |
2061 | else | |
8f0d8cd8 PP |
2062 | { |
2063 | auto __sz = size(); | |
6e00d9bb | 2064 | return counted_iterator(ranges::begin(_M_base), __sz); |
8f0d8cd8 | 2065 | } |
cba9ef06 PP |
2066 | } |
2067 | else | |
6e00d9bb | 2068 | return counted_iterator(ranges::begin(_M_base), _M_count); |
cba9ef06 PP |
2069 | } |
2070 | ||
2071 | constexpr auto | |
2072 | begin() const requires range<const _Vp> | |
2073 | { | |
2074 | if constexpr (sized_range<const _Vp>) | |
2075 | { | |
2076 | if constexpr (random_access_range<const _Vp>) | |
2077 | return ranges::begin(_M_base); | |
2078 | else | |
8f0d8cd8 PP |
2079 | { |
2080 | auto __sz = size(); | |
6e00d9bb | 2081 | return counted_iterator(ranges::begin(_M_base), __sz); |
8f0d8cd8 | 2082 | } |
cba9ef06 PP |
2083 | } |
2084 | else | |
6e00d9bb | 2085 | return counted_iterator(ranges::begin(_M_base), _M_count); |
cba9ef06 PP |
2086 | } |
2087 | ||
2088 | constexpr auto | |
2089 | end() requires (!__detail::__simple_view<_Vp>) | |
2090 | { | |
2091 | if constexpr (sized_range<_Vp>) | |
2092 | { | |
2093 | if constexpr (random_access_range<_Vp>) | |
2094 | return ranges::begin(_M_base) + size(); | |
2095 | else | |
2096 | return default_sentinel; | |
2097 | } | |
2098 | else | |
2099 | return _Sentinel<false>{ranges::end(_M_base)}; | |
2100 | } | |
2101 | ||
2102 | constexpr auto | |
2103 | end() const requires range<const _Vp> | |
2104 | { | |
2105 | if constexpr (sized_range<const _Vp>) | |
2106 | { | |
2107 | if constexpr (random_access_range<const _Vp>) | |
2108 | return ranges::begin(_M_base) + size(); | |
2109 | else | |
2110 | return default_sentinel; | |
2111 | } | |
2112 | else | |
2113 | return _Sentinel<true>{ranges::end(_M_base)}; | |
2114 | } | |
2115 | ||
2116 | constexpr auto | |
2117 | size() requires sized_range<_Vp> | |
2118 | { | |
2119 | auto __n = ranges::size(_M_base); | |
c1ce418a | 2120 | return std::min(__n, static_cast<decltype(__n)>(_M_count)); |
cba9ef06 PP |
2121 | } |
2122 | ||
2123 | constexpr auto | |
2124 | size() const requires sized_range<const _Vp> | |
2125 | { | |
2126 | auto __n = ranges::size(_M_base); | |
c1ce418a | 2127 | return std::min(__n, static_cast<decltype(__n)>(_M_count)); |
cba9ef06 PP |
2128 | } |
2129 | }; | |
2130 | ||
50106208 PP |
2131 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
2132 | // 3447. Deduction guides for take_view and drop_view have different | |
2133 | // constraints | |
2134 | template<typename _Range> | |
cba9ef06 | 2135 | take_view(_Range&&, range_difference_t<_Range>) |
aca60ecf | 2136 | -> take_view<views::all_t<_Range>>; |
cba9ef06 | 2137 | |
39bf4f14 JW |
2138 | template<typename _Tp> |
2139 | inline constexpr bool enable_borrowed_range<take_view<_Tp>> | |
2140 | = enable_borrowed_range<_Tp>; | |
2141 | ||
cba9ef06 PP |
2142 | namespace views |
2143 | { | |
a25321ca PP |
2144 | namespace __detail |
2145 | { | |
9626e447 PP |
2146 | template<typename _Range> |
2147 | inline constexpr bool __is_empty_view = false; | |
2148 | ||
2149 | template<typename _Tp> | |
2150 | inline constexpr bool __is_empty_view<empty_view<_Tp>> = true; | |
2151 | ||
2152 | template<typename _Range> | |
2153 | inline constexpr bool __is_basic_string_view = false; | |
2154 | ||
2155 | template<typename _CharT, typename _Traits> | |
2156 | inline constexpr bool __is_basic_string_view<basic_string_view<_CharT, _Traits>> | |
2157 | = true; | |
2158 | ||
2159 | template<typename _Range> | |
2160 | inline constexpr bool __is_subrange = false; | |
2161 | ||
2162 | template<typename _Iter, typename _Sent, subrange_kind _Kind> | |
2163 | inline constexpr bool __is_subrange<subrange<_Iter, _Sent, _Kind>> = true; | |
2164 | ||
2165 | template<typename _Range> | |
2166 | inline constexpr bool __is_iota_view = false; | |
2167 | ||
2168 | template<typename _Winc, typename _Bound> | |
2169 | inline constexpr bool __is_iota_view<iota_view<_Winc, _Bound>> = true; | |
2170 | ||
2171 | template<typename _Range, typename _Dp> | |
a25321ca | 2172 | concept __can_take_view |
9626e447 | 2173 | = requires { take_view(std::declval<_Range>(), std::declval<_Dp>()); }; |
a25321ca PP |
2174 | } // namespace __detail |
2175 | ||
2176 | struct _Take : __adaptor::_RangeAdaptor<_Take> | |
2177 | { | |
9626e447 PP |
2178 | template<viewable_range _Range, typename _Dp = range_difference_t<_Range>> |
2179 | requires __detail::__can_take_view<_Range, _Dp> | |
a25321ca | 2180 | constexpr auto |
9626e447 | 2181 | operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const |
a25321ca | 2182 | { |
9626e447 PP |
2183 | using _Tp = remove_cvref_t<_Range>; |
2184 | if constexpr (__detail::__is_empty_view<_Tp>) | |
2185 | return _Tp(); | |
2186 | else if constexpr (random_access_range<_Tp> | |
2187 | && sized_range<_Tp> | |
2188 | && (std::__detail::__is_span<_Tp> | |
2189 | || __detail::__is_basic_string_view<_Tp> | |
2190 | || __detail::__is_subrange<_Tp> | |
2191 | || __detail::__is_iota_view<_Tp>)) | |
2192 | { | |
2193 | __n = std::min<_Dp>(ranges::distance(__r), __n); | |
2194 | auto __begin = ranges::begin(__r); | |
2195 | auto __end = __begin + __n; | |
2196 | if constexpr (std::__detail::__is_span<_Tp>) | |
2197 | return span<typename _Tp::element_type>(__begin, __end); | |
2198 | else if constexpr (__detail::__is_basic_string_view<_Tp>) | |
2199 | return _Tp(__begin, __end); | |
2200 | else if constexpr (__detail::__is_subrange<_Tp>) | |
2201 | return subrange<iterator_t<_Tp>>(__begin, __end); | |
2202 | else | |
2203 | return iota_view(*__begin, *__end); | |
2204 | } | |
2205 | else | |
2206 | return take_view(std::forward<_Range>(__r), __n); | |
a25321ca PP |
2207 | } |
2208 | ||
2209 | using _RangeAdaptor<_Take>::operator(); | |
2210 | static constexpr int _S_arity = 2; | |
0f4a2fb4 PP |
2211 | // The count argument of views::take is not always simple -- it can be |
2212 | // e.g. a move-only class that's implicitly convertible to the difference | |
2213 | // type. But an integer-like count argument is surely simple. | |
2214 | template<typename _Tp> | |
2215 | static constexpr bool _S_has_simple_extra_args | |
2216 | = ranges::__detail::__is_integer_like<_Tp>; | |
a25321ca PP |
2217 | }; |
2218 | ||
2219 | inline constexpr _Take take; | |
cba9ef06 PP |
2220 | } // namespace views |
2221 | ||
2222 | template<view _Vp, typename _Pred> | |
2223 | requires input_range<_Vp> && is_object_v<_Pred> | |
2224 | && indirect_unary_predicate<const _Pred, iterator_t<_Vp>> | |
2225 | class take_while_view : public view_interface<take_while_view<_Vp, _Pred>> | |
2226 | { | |
2227 | template<bool _Const> | |
2228 | struct _Sentinel | |
2229 | { | |
2230 | private: | |
8017d95c | 2231 | using _Base = __detail::__maybe_const_t<_Const, _Vp>; |
cba9ef06 PP |
2232 | |
2233 | sentinel_t<_Base> _M_end = sentinel_t<_Base>(); | |
2234 | const _Pred* _M_pred = nullptr; | |
2235 | ||
2236 | public: | |
2237 | _Sentinel() = default; | |
2238 | ||
2239 | constexpr explicit | |
2240 | _Sentinel(sentinel_t<_Base> __end, const _Pred* __pred) | |
2241 | : _M_end(__end), _M_pred(__pred) | |
2242 | { } | |
2243 | ||
2244 | constexpr | |
2245 | _Sentinel(_Sentinel<!_Const> __s) | |
2246 | requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> | |
2247 | : _M_end(__s._M_end), _M_pred(__s._M_pred) | |
2248 | { } | |
2249 | ||
2250 | constexpr sentinel_t<_Base> | |
2251 | base() const { return _M_end; } | |
2252 | ||
2253 | friend constexpr bool | |
2254 | operator==(const iterator_t<_Base>& __x, const _Sentinel& __y) | |
2255 | { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } | |
ba49e9eb | 2256 | |
e066821b PP |
2257 | template<bool _OtherConst = !_Const, |
2258 | typename _Base2 = __detail::__maybe_const_t<_OtherConst, _Vp>> | |
2259 | requires sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>> | |
2260 | friend constexpr bool | |
2261 | operator==(const iterator_t<_Base2>& __x, const _Sentinel& __y) | |
2262 | { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } | |
2263 | ||
ba49e9eb | 2264 | friend _Sentinel<!_Const>; |
cba9ef06 PP |
2265 | }; |
2266 | ||
361e32ee | 2267 | _Vp _M_base = _Vp(); |
53b1c382 | 2268 | [[no_unique_address]] __detail::__box<_Pred> _M_pred; |
cba9ef06 PP |
2269 | |
2270 | public: | |
4b4f5666 PP |
2271 | take_while_view() requires (default_initializable<_Vp> |
2272 | && default_initializable<_Pred>) | |
2273 | = default; | |
cba9ef06 PP |
2274 | |
2275 | constexpr | |
2276 | take_while_view(_Vp base, _Pred __pred) | |
53b1c382 | 2277 | : _M_base(std::move(base)), _M_pred(std::move(__pred)) |
361e32ee | 2278 | { } |
cba9ef06 PP |
2279 | |
2280 | constexpr _Vp | |
2281 | base() const& requires copy_constructible<_Vp> | |
2282 | { return _M_base; } | |
2283 | ||
2284 | constexpr _Vp | |
2285 | base() && | |
2286 | { return std::move(_M_base); } | |
2287 | ||
2288 | constexpr const _Pred& | |
2289 | pred() const | |
2290 | { return *_M_pred; } | |
2291 | ||
2292 | constexpr auto | |
2293 | begin() requires (!__detail::__simple_view<_Vp>) | |
2294 | { return ranges::begin(_M_base); } | |
2295 | ||
2296 | constexpr auto | |
2297 | begin() const requires range<const _Vp> | |
c5aad5a4 | 2298 | && indirect_unary_predicate<const _Pred, iterator_t<const _Vp>> |
cba9ef06 PP |
2299 | { return ranges::begin(_M_base); } |
2300 | ||
2301 | constexpr auto | |
2302 | end() requires (!__detail::__simple_view<_Vp>) | |
2303 | { return _Sentinel<false>(ranges::end(_M_base), | |
2304 | std::__addressof(*_M_pred)); } | |
2305 | ||
2306 | constexpr auto | |
2307 | end() const requires range<const _Vp> | |
c5aad5a4 | 2308 | && indirect_unary_predicate<const _Pred, iterator_t<const _Vp>> |
cba9ef06 PP |
2309 | { return _Sentinel<true>(ranges::end(_M_base), |
2310 | std::__addressof(*_M_pred)); } | |
2311 | }; | |
2312 | ||
2313 | template<typename _Range, typename _Pred> | |
2314 | take_while_view(_Range&&, _Pred) | |
aca60ecf | 2315 | -> take_while_view<views::all_t<_Range>, _Pred>; |
cba9ef06 PP |
2316 | |
2317 | namespace views | |
2318 | { | |
a25321ca PP |
2319 | namespace __detail |
2320 | { | |
2321 | template<typename _Range, typename _Pred> | |
2322 | concept __can_take_while_view | |
6e00d9bb | 2323 | = requires { take_while_view(std::declval<_Range>(), std::declval<_Pred>()); }; |
a25321ca PP |
2324 | } // namespace __detail |
2325 | ||
2326 | struct _TakeWhile : __adaptor::_RangeAdaptor<_TakeWhile> | |
2327 | { | |
2328 | template<viewable_range _Range, typename _Pred> | |
2329 | requires __detail::__can_take_while_view<_Range, _Pred> | |
2330 | constexpr auto | |
c8b024fa | 2331 | operator() [[nodiscard]] (_Range&& __r, _Pred&& __p) const |
a25321ca | 2332 | { |
6e00d9bb | 2333 | return take_while_view(std::forward<_Range>(__r), std::forward<_Pred>(__p)); |
a25321ca PP |
2334 | } |
2335 | ||
2336 | using _RangeAdaptor<_TakeWhile>::operator(); | |
2337 | static constexpr int _S_arity = 2; | |
57ed620e | 2338 | static constexpr bool _S_has_simple_extra_args = true; |
a25321ca PP |
2339 | }; |
2340 | ||
2341 | inline constexpr _TakeWhile take_while; | |
cba9ef06 PP |
2342 | } // namespace views |
2343 | ||
2344 | template<view _Vp> | |
2345 | class drop_view : public view_interface<drop_view<_Vp>> | |
2346 | { | |
2347 | private: | |
361e32ee | 2348 | _Vp _M_base = _Vp(); |
53b1c382 | 2349 | range_difference_t<_Vp> _M_count = 0; |
cba9ef06 | 2350 | |
aecea415 JW |
2351 | // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies |
2352 | // both random_access_range and sized_range. Otherwise, cache its result. | |
2353 | static constexpr bool _S_needs_cached_begin | |
2354 | = !(random_access_range<const _Vp> && sized_range<const _Vp>); | |
a1535015 | 2355 | [[no_unique_address]] |
4c391563 JW |
2356 | __detail::__maybe_present_t<_S_needs_cached_begin, |
2357 | __detail::_CachedPosition<_Vp>> | |
2358 | _M_cached_begin; | |
a1535015 | 2359 | |
cba9ef06 | 2360 | public: |
4b4f5666 | 2361 | drop_view() requires default_initializable<_Vp> = default; |
cba9ef06 PP |
2362 | |
2363 | constexpr | |
2364 | drop_view(_Vp __base, range_difference_t<_Vp> __count) | |
53b1c382 | 2365 | : _M_base(std::move(__base)), _M_count(__count) |
cba9ef06 PP |
2366 | { __glibcxx_assert(__count >= 0); } |
2367 | ||
2368 | constexpr _Vp | |
2369 | base() const& requires copy_constructible<_Vp> | |
2370 | { return _M_base; } | |
2371 | ||
2372 | constexpr _Vp | |
2373 | base() && | |
2374 | { return std::move(_M_base); } | |
2375 | ||
aecea415 | 2376 | // This overload is disabled for simple views with constant-time begin(). |
cba9ef06 | 2377 | constexpr auto |
aecea415 JW |
2378 | begin() |
2379 | requires (!(__detail::__simple_view<_Vp> | |
2380 | && random_access_range<const _Vp> | |
2381 | && sized_range<const _Vp>)) | |
cba9ef06 | 2382 | { |
a1535015 PP |
2383 | if constexpr (_S_needs_cached_begin) |
2384 | if (_M_cached_begin._M_has_value()) | |
2385 | return _M_cached_begin._M_get(_M_base); | |
2386 | ||
2387 | auto __it = ranges::next(ranges::begin(_M_base), | |
2388 | _M_count, ranges::end(_M_base)); | |
2389 | if constexpr (_S_needs_cached_begin) | |
2390 | _M_cached_begin._M_set(_M_base, __it); | |
2391 | return __it; | |
cba9ef06 PP |
2392 | } |
2393 | ||
aecea415 JW |
2394 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
2395 | // 3482. drop_view's const begin should additionally require sized_range | |
cba9ef06 | 2396 | constexpr auto |
aecea415 JW |
2397 | begin() const |
2398 | requires random_access_range<const _Vp> && sized_range<const _Vp> | |
cba9ef06 PP |
2399 | { |
2400 | return ranges::next(ranges::begin(_M_base), _M_count, | |
2401 | ranges::end(_M_base)); | |
2402 | } | |
2403 | ||
2404 | constexpr auto | |
2405 | end() requires (!__detail::__simple_view<_Vp>) | |
2406 | { return ranges::end(_M_base); } | |
2407 | ||
2408 | constexpr auto | |
2409 | end() const requires range<const _Vp> | |
2410 | { return ranges::end(_M_base); } | |
2411 | ||
2412 | constexpr auto | |
2413 | size() requires sized_range<_Vp> | |
2414 | { | |
2415 | const auto __s = ranges::size(_M_base); | |
2416 | const auto __c = static_cast<decltype(__s)>(_M_count); | |
2417 | return __s < __c ? 0 : __s - __c; | |
2418 | } | |
2419 | ||
2420 | constexpr auto | |
2421 | size() const requires sized_range<const _Vp> | |
2422 | { | |
2423 | const auto __s = ranges::size(_M_base); | |
2424 | const auto __c = static_cast<decltype(__s)>(_M_count); | |
2425 | return __s < __c ? 0 : __s - __c; | |
2426 | } | |
2427 | }; | |
2428 | ||
2429 | template<typename _Range> | |
2430 | drop_view(_Range&&, range_difference_t<_Range>) | |
aca60ecf | 2431 | -> drop_view<views::all_t<_Range>>; |
cba9ef06 | 2432 | |
39bf4f14 JW |
2433 | template<typename _Tp> |
2434 | inline constexpr bool enable_borrowed_range<drop_view<_Tp>> | |
2435 | = enable_borrowed_range<_Tp>; | |
2436 | ||
cba9ef06 PP |
2437 | namespace views |
2438 | { | |
a25321ca PP |
2439 | namespace __detail |
2440 | { | |
9626e447 | 2441 | template<typename _Range, typename _Dp> |
a25321ca | 2442 | concept __can_drop_view |
9626e447 | 2443 | = requires { drop_view(std::declval<_Range>(), std::declval<_Dp>()); }; |
a25321ca PP |
2444 | } // namespace __detail |
2445 | ||
2446 | struct _Drop : __adaptor::_RangeAdaptor<_Drop> | |
2447 | { | |
9626e447 PP |
2448 | template<viewable_range _Range, typename _Dp = range_difference_t<_Range>> |
2449 | requires __detail::__can_drop_view<_Range, _Dp> | |
a25321ca | 2450 | constexpr auto |
9626e447 | 2451 | operator() [[nodiscard]] (_Range&& __r, type_identity_t<_Dp> __n) const |
a25321ca | 2452 | { |
9626e447 PP |
2453 | using _Tp = remove_cvref_t<_Range>; |
2454 | if constexpr (__detail::__is_empty_view<_Tp>) | |
2455 | return _Tp(); | |
2456 | else if constexpr (random_access_range<_Tp> | |
2457 | && sized_range<_Tp> | |
2458 | && (std::__detail::__is_span<_Tp> | |
2459 | || __detail::__is_basic_string_view<_Tp> | |
2460 | || __detail::__is_iota_view<_Tp> | |
2461 | || __detail::__is_subrange<_Tp>)) | |
2462 | { | |
2463 | __n = std::min<_Dp>(ranges::distance(__r), __n); | |
2464 | auto __begin = ranges::begin(__r) + __n; | |
2465 | auto __end = ranges::end(__r); | |
2466 | if constexpr (std::__detail::__is_span<_Tp>) | |
2467 | return span<typename _Tp::element_type>(__begin, __end); | |
2468 | else if constexpr (__detail::__is_subrange<_Tp>) | |
2469 | { | |
2470 | if constexpr (_Tp::_S_store_size) | |
2471 | { | |
2472 | using ranges::__detail::__to_unsigned_like; | |
2473 | auto __m = ranges::distance(__r) - __n; | |
2474 | return _Tp(__begin, __end, __to_unsigned_like(__m)); | |
2475 | } | |
2476 | else | |
2477 | return _Tp(__begin, __end); | |
2478 | } | |
2479 | else | |
2480 | return _Tp(__begin, __end); | |
2481 | } | |
2482 | else | |
2483 | return drop_view(std::forward<_Range>(__r), __n); | |
a25321ca PP |
2484 | } |
2485 | ||
2486 | using _RangeAdaptor<_Drop>::operator(); | |
2487 | static constexpr int _S_arity = 2; | |
0f4a2fb4 PP |
2488 | template<typename _Tp> |
2489 | static constexpr bool _S_has_simple_extra_args | |
2490 | = _Take::_S_has_simple_extra_args<_Tp>; | |
a25321ca PP |
2491 | }; |
2492 | ||
2493 | inline constexpr _Drop drop; | |
cba9ef06 PP |
2494 | } // namespace views |
2495 | ||
2496 | template<view _Vp, typename _Pred> | |
2497 | requires input_range<_Vp> && is_object_v<_Pred> | |
2498 | && indirect_unary_predicate<const _Pred, iterator_t<_Vp>> | |
2499 | class drop_while_view : public view_interface<drop_while_view<_Vp, _Pred>> | |
2500 | { | |
2501 | private: | |
53b1c382 | 2502 | _Vp _M_base = _Vp(); |
42907ca9 | 2503 | [[no_unique_address]] __detail::__box<_Pred> _M_pred; |
a1535015 | 2504 | [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; |
cba9ef06 PP |
2505 | |
2506 | public: | |
4b4f5666 PP |
2507 | drop_while_view() requires (default_initializable<_Vp> |
2508 | && default_initializable<_Pred>) | |
2509 | = default; | |
cba9ef06 PP |
2510 | |
2511 | constexpr | |
2512 | drop_while_view(_Vp __base, _Pred __pred) | |
53b1c382 | 2513 | : _M_base(std::move(__base)), _M_pred(std::move(__pred)) |
cba9ef06 PP |
2514 | { } |
2515 | ||
2516 | constexpr _Vp | |
2517 | base() const& requires copy_constructible<_Vp> | |
2518 | { return _M_base; } | |
2519 | ||
2520 | constexpr _Vp | |
2521 | base() && | |
2522 | { return std::move(_M_base); } | |
2523 | ||
2524 | constexpr const _Pred& | |
2525 | pred() const | |
2526 | { return *_M_pred; } | |
2527 | ||
2528 | constexpr auto | |
2529 | begin() | |
2530 | { | |
a1535015 PP |
2531 | if (_M_cached_begin._M_has_value()) |
2532 | return _M_cached_begin._M_get(_M_base); | |
2533 | ||
11784fe2 | 2534 | __glibcxx_assert(_M_pred.has_value()); |
2786064d PP |
2535 | auto __it = ranges::find_if_not(ranges::begin(_M_base), |
2536 | ranges::end(_M_base), | |
2537 | std::cref(*_M_pred)); | |
a1535015 PP |
2538 | _M_cached_begin._M_set(_M_base, __it); |
2539 | return __it; | |
cba9ef06 PP |
2540 | } |
2541 | ||
2542 | constexpr auto | |
2543 | end() | |
2544 | { return ranges::end(_M_base); } | |
2545 | }; | |
2546 | ||
2547 | template<typename _Range, typename _Pred> | |
2548 | drop_while_view(_Range&&, _Pred) | |
aca60ecf | 2549 | -> drop_while_view<views::all_t<_Range>, _Pred>; |
cba9ef06 | 2550 | |
39bf4f14 JW |
2551 | template<typename _Tp, typename _Pred> |
2552 | inline constexpr bool enable_borrowed_range<drop_while_view<_Tp, _Pred>> | |
2553 | = enable_borrowed_range<_Tp>; | |
2554 | ||
cba9ef06 PP |
2555 | namespace views |
2556 | { | |
a25321ca PP |
2557 | namespace __detail |
2558 | { | |
2559 | template<typename _Range, typename _Pred> | |
2560 | concept __can_drop_while_view | |
6e00d9bb | 2561 | = requires { drop_while_view(std::declval<_Range>(), std::declval<_Pred>()); }; |
a25321ca PP |
2562 | } // namespace __detail |
2563 | ||
2564 | struct _DropWhile : __adaptor::_RangeAdaptor<_DropWhile> | |
2565 | { | |
2566 | template<viewable_range _Range, typename _Pred> | |
2567 | requires __detail::__can_drop_while_view<_Range, _Pred> | |
2568 | constexpr auto | |
c8b024fa | 2569 | operator() [[nodiscard]] (_Range&& __r, _Pred&& __p) const |
a25321ca | 2570 | { |
6e00d9bb PP |
2571 | return drop_while_view(std::forward<_Range>(__r), |
2572 | std::forward<_Pred>(__p)); | |
a25321ca PP |
2573 | } |
2574 | ||
2575 | using _RangeAdaptor<_DropWhile>::operator(); | |
2576 | static constexpr int _S_arity = 2; | |
57ed620e | 2577 | static constexpr bool _S_has_simple_extra_args = true; |
a25321ca PP |
2578 | }; |
2579 | ||
2580 | inline constexpr _DropWhile drop_while; | |
cba9ef06 PP |
2581 | } // namespace views |
2582 | ||
2583 | template<input_range _Vp> | |
2584 | requires view<_Vp> && input_range<range_reference_t<_Vp>> | |
cba9ef06 PP |
2585 | class join_view : public view_interface<join_view<_Vp>> |
2586 | { | |
2587 | private: | |
2588 | using _InnerRange = range_reference_t<_Vp>; | |
2589 | ||
902b40c7 PP |
2590 | template<bool _Const> |
2591 | using _Base = __detail::__maybe_const_t<_Const, _Vp>; | |
2592 | ||
2593 | template<bool _Const> | |
2594 | using _Outer_iter = iterator_t<_Base<_Const>>; | |
2595 | ||
2596 | template<bool _Const> | |
2597 | using _Inner_iter = iterator_t<range_reference_t<_Base<_Const>>>; | |
2598 | ||
2599 | template<bool _Const> | |
2600 | static constexpr bool _S_ref_is_glvalue | |
2601 | = is_reference_v<range_reference_t<_Base<_Const>>>; | |
2602 | ||
2603 | template<bool _Const> | |
2604 | struct __iter_cat | |
2605 | { }; | |
2606 | ||
2607 | template<bool _Const> | |
2608 | requires _S_ref_is_glvalue<_Const> | |
2609 | && forward_range<_Base<_Const>> | |
2610 | && forward_range<range_reference_t<_Base<_Const>>> | |
2611 | struct __iter_cat<_Const> | |
2612 | { | |
2613 | private: | |
2614 | static constexpr auto | |
2615 | _S_iter_cat() | |
2616 | { | |
2617 | using _Outer_iter = join_view::_Outer_iter<_Const>; | |
2618 | using _Inner_iter = join_view::_Inner_iter<_Const>; | |
2619 | using _OuterCat = typename iterator_traits<_Outer_iter>::iterator_category; | |
2620 | using _InnerCat = typename iterator_traits<_Inner_iter>::iterator_category; | |
2621 | if constexpr (derived_from<_OuterCat, bidirectional_iterator_tag> | |
6667274b PP |
2622 | && derived_from<_InnerCat, bidirectional_iterator_tag> |
2623 | && common_range<range_reference_t<_Base<_Const>>>) | |
902b40c7 PP |
2624 | return bidirectional_iterator_tag{}; |
2625 | else if constexpr (derived_from<_OuterCat, forward_iterator_tag> | |
2626 | && derived_from<_InnerCat, forward_iterator_tag>) | |
2627 | return forward_iterator_tag{}; | |
2628 | else | |
2629 | return input_iterator_tag{}; | |
2630 | } | |
2631 | public: | |
2632 | using iterator_category = decltype(_S_iter_cat()); | |
2633 | }; | |
2634 | ||
cba9ef06 PP |
2635 | template<bool _Const> |
2636 | struct _Sentinel; | |
2637 | ||
2638 | template<bool _Const> | |
902b40c7 | 2639 | struct _Iterator : __iter_cat<_Const> |
cba9ef06 PP |
2640 | { |
2641 | private: | |
8017d95c | 2642 | using _Parent = __detail::__maybe_const_t<_Const, join_view>; |
902b40c7 | 2643 | using _Base = join_view::_Base<_Const>; |
cba9ef06 PP |
2644 | |
2645 | static constexpr bool _S_ref_is_glvalue | |
902b40c7 | 2646 | = join_view::_S_ref_is_glvalue<_Const>; |
cba9ef06 PP |
2647 | |
2648 | constexpr void | |
2649 | _M_satisfy() | |
2650 | { | |
237dde3d | 2651 | auto __update_inner = [this] (const iterator_t<_Base>& __x) -> auto&& { |
cba9ef06 | 2652 | if constexpr (_S_ref_is_glvalue) |
237dde3d | 2653 | return *__x; |
cba9ef06 | 2654 | else |
237dde3d | 2655 | return _M_parent->_M_inner._M_emplace_deref(__x); |
cba9ef06 PP |
2656 | }; |
2657 | ||
2658 | for (; _M_outer != ranges::end(_M_parent->_M_base); ++_M_outer) | |
2659 | { | |
237dde3d | 2660 | auto&& __inner = __update_inner(_M_outer); |
d4a788c7 PP |
2661 | _M_inner = ranges::begin(__inner); |
2662 | if (_M_inner != ranges::end(__inner)) | |
cba9ef06 PP |
2663 | return; |
2664 | } | |
2665 | ||
2666 | if constexpr (_S_ref_is_glvalue) | |
a5b213dd | 2667 | _M_inner = _Inner_iter(); |
cba9ef06 PP |
2668 | } |
2669 | ||
2670 | static constexpr auto | |
2671 | _S_iter_concept() | |
2672 | { | |
2673 | if constexpr (_S_ref_is_glvalue | |
2674 | && bidirectional_range<_Base> | |
6667274b PP |
2675 | && bidirectional_range<range_reference_t<_Base>> |
2676 | && common_range<range_reference_t<_Base>>) | |
cba9ef06 PP |
2677 | return bidirectional_iterator_tag{}; |
2678 | else if constexpr (_S_ref_is_glvalue | |
2679 | && forward_range<_Base> | |
2680 | && forward_range<range_reference_t<_Base>>) | |
2681 | return forward_iterator_tag{}; | |
2682 | else | |
2683 | return input_iterator_tag{}; | |
2684 | } | |
2685 | ||
902b40c7 PP |
2686 | using _Outer_iter = join_view::_Outer_iter<_Const>; |
2687 | using _Inner_iter = join_view::_Inner_iter<_Const>; | |
a5b213dd JW |
2688 | |
2689 | _Outer_iter _M_outer = _Outer_iter(); | |
2690 | _Inner_iter _M_inner = _Inner_iter(); | |
cba9ef06 PP |
2691 | _Parent* _M_parent = nullptr; |
2692 | ||
2693 | public: | |
2694 | using iterator_concept = decltype(_S_iter_concept()); | |
902b40c7 | 2695 | // iterator_category defined in __join_view_iter_cat |
cba9ef06 PP |
2696 | using value_type = range_value_t<range_reference_t<_Base>>; |
2697 | using difference_type | |
2698 | = common_type_t<range_difference_t<_Base>, | |
2699 | range_difference_t<range_reference_t<_Base>>>; | |
2700 | ||
4b4f5666 PP |
2701 | _Iterator() requires (default_initializable<_Outer_iter> |
2702 | && default_initializable<_Inner_iter>) | |
2703 | = default; | |
cba9ef06 | 2704 | |
cba9ef06 | 2705 | constexpr |
afb8da7f | 2706 | _Iterator(_Parent* __parent, _Outer_iter __outer) |
cba9ef06 | 2707 | : _M_outer(std::move(__outer)), |
afb8da7f | 2708 | _M_parent(__parent) |
cba9ef06 PP |
2709 | { _M_satisfy(); } |
2710 | ||
2711 | constexpr | |
2712 | _Iterator(_Iterator<!_Const> __i) | |
2713 | requires _Const | |
a5b213dd JW |
2714 | && convertible_to<iterator_t<_Vp>, _Outer_iter> |
2715 | && convertible_to<iterator_t<_InnerRange>, _Inner_iter> | |
0e1bb3c8 | 2716 | : _M_outer(std::move(__i._M_outer)), _M_inner(std::move(__i._M_inner)), |
cba9ef06 PP |
2717 | _M_parent(__i._M_parent) |
2718 | { } | |
2719 | ||
2720 | constexpr decltype(auto) | |
2721 | operator*() const | |
2722 | { return *_M_inner; } | |
2723 | ||
d4a788c7 PP |
2724 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
2725 | // 3500. join_view::iterator::operator->() is bogus | |
2726 | constexpr _Inner_iter | |
cba9ef06 | 2727 | operator->() const |
d4a788c7 PP |
2728 | requires __detail::__has_arrow<_Inner_iter> |
2729 | && copyable<_Inner_iter> | |
cba9ef06 PP |
2730 | { return _M_inner; } |
2731 | ||
2732 | constexpr _Iterator& | |
2733 | operator++() | |
2734 | { | |
85ef4b8d | 2735 | auto&& __inner_range = [this] () -> auto&& { |
cba9ef06 PP |
2736 | if constexpr (_S_ref_is_glvalue) |
2737 | return *_M_outer; | |
2738 | else | |
237dde3d | 2739 | return *_M_parent->_M_inner; |
cba9ef06 PP |
2740 | }(); |
2741 | if (++_M_inner == ranges::end(__inner_range)) | |
2742 | { | |
2743 | ++_M_outer; | |
2744 | _M_satisfy(); | |
2745 | } | |
2746 | return *this; | |
2747 | } | |
2748 | ||
2749 | constexpr void | |
2750 | operator++(int) | |
2751 | { ++*this; } | |
2752 | ||
2753 | constexpr _Iterator | |
2754 | operator++(int) | |
2755 | requires _S_ref_is_glvalue && forward_range<_Base> | |
2756 | && forward_range<range_reference_t<_Base>> | |
2757 | { | |
2758 | auto __tmp = *this; | |
2759 | ++*this; | |
2760 | return __tmp; | |
2761 | } | |
2762 | ||
2763 | constexpr _Iterator& | |
2764 | operator--() | |
2765 | requires _S_ref_is_glvalue && bidirectional_range<_Base> | |
2766 | && bidirectional_range<range_reference_t<_Base>> | |
55c4b3f4 | 2767 | && common_range<range_reference_t<_Base>> |
cba9ef06 PP |
2768 | { |
2769 | if (_M_outer == ranges::end(_M_parent->_M_base)) | |
2770 | _M_inner = ranges::end(*--_M_outer); | |
2771 | while (_M_inner == ranges::begin(*_M_outer)) | |
2772 | _M_inner = ranges::end(*--_M_outer); | |
2773 | --_M_inner; | |
2774 | return *this; | |
2775 | } | |
2776 | ||
2777 | constexpr _Iterator | |
2778 | operator--(int) | |
2779 | requires _S_ref_is_glvalue && bidirectional_range<_Base> | |
2780 | && bidirectional_range<range_reference_t<_Base>> | |
55c4b3f4 | 2781 | && common_range<range_reference_t<_Base>> |
cba9ef06 PP |
2782 | { |
2783 | auto __tmp = *this; | |
2784 | --*this; | |
2785 | return __tmp; | |
2786 | } | |
2787 | ||
2788 | friend constexpr bool | |
2789 | operator==(const _Iterator& __x, const _Iterator& __y) | |
2790 | requires _S_ref_is_glvalue | |
a5b213dd JW |
2791 | && equality_comparable<_Outer_iter> |
2792 | && equality_comparable<_Inner_iter> | |
cba9ef06 PP |
2793 | { |
2794 | return (__x._M_outer == __y._M_outer | |
2795 | && __x._M_inner == __y._M_inner); | |
2796 | } | |
2797 | ||
2798 | friend constexpr decltype(auto) | |
2799 | iter_move(const _Iterator& __i) | |
2800 | noexcept(noexcept(ranges::iter_move(__i._M_inner))) | |
2801 | { return ranges::iter_move(__i._M_inner); } | |
2802 | ||
2803 | friend constexpr void | |
2804 | iter_swap(const _Iterator& __x, const _Iterator& __y) | |
2805 | noexcept(noexcept(ranges::iter_swap(__x._M_inner, __y._M_inner))) | |
2663727d | 2806 | requires indirectly_swappable<_Inner_iter> |
cba9ef06 PP |
2807 | { return ranges::iter_swap(__x._M_inner, __y._M_inner); } |
2808 | ||
242b4fb7 | 2809 | friend _Iterator<!_Const>; |
6c2582c0 | 2810 | template<bool> friend struct _Sentinel; |
cba9ef06 PP |
2811 | }; |
2812 | ||
2813 | template<bool _Const> | |
2814 | struct _Sentinel | |
2815 | { | |
2816 | private: | |
8017d95c | 2817 | using _Parent = __detail::__maybe_const_t<_Const, join_view>; |
902b40c7 | 2818 | using _Base = join_view::_Base<_Const>; |
cba9ef06 | 2819 | |
6c2582c0 JW |
2820 | template<bool _Const2> |
2821 | constexpr bool | |
2822 | __equal(const _Iterator<_Const2>& __i) const | |
2823 | { return __i._M_outer == _M_end; } | |
cba9ef06 PP |
2824 | |
2825 | sentinel_t<_Base> _M_end = sentinel_t<_Base>(); | |
2826 | ||
2827 | public: | |
2828 | _Sentinel() = default; | |
2829 | ||
2830 | constexpr explicit | |
afb8da7f PP |
2831 | _Sentinel(_Parent* __parent) |
2832 | : _M_end(ranges::end(__parent->_M_base)) | |
cba9ef06 PP |
2833 | { } |
2834 | ||
2835 | constexpr | |
2836 | _Sentinel(_Sentinel<!_Const> __s) | |
2837 | requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> | |
2838 | : _M_end(std::move(__s._M_end)) | |
2839 | { } | |
2840 | ||
6c2582c0 JW |
2841 | template<bool _Const2> |
2842 | requires sentinel_for<sentinel_t<_Base>, | |
2843 | iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> | |
2844 | friend constexpr bool | |
2845 | operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) | |
2846 | { return __y.__equal(__x); } | |
6aa2ca21 PP |
2847 | |
2848 | friend _Sentinel<!_Const>; | |
cba9ef06 PP |
2849 | }; |
2850 | ||
53b1c382 | 2851 | _Vp _M_base = _Vp(); |
242b4fb7 | 2852 | [[no_unique_address]] |
237dde3d | 2853 | __detail::__non_propagating_cache<remove_cv_t<_InnerRange>> _M_inner; |
cba9ef06 PP |
2854 | |
2855 | public: | |
4b4f5666 | 2856 | join_view() requires default_initializable<_Vp> = default; |
cba9ef06 PP |
2857 | |
2858 | constexpr explicit | |
2859 | join_view(_Vp __base) | |
2860 | : _M_base(std::move(__base)) | |
2861 | { } | |
2862 | ||
cba9ef06 PP |
2863 | constexpr _Vp |
2864 | base() const& requires copy_constructible<_Vp> | |
2865 | { return _M_base; } | |
2866 | ||
2867 | constexpr _Vp | |
2868 | base() && | |
2869 | { return std::move(_M_base); } | |
2870 | ||
2871 | constexpr auto | |
2872 | begin() | |
2873 | { | |
242b4fb7 PP |
2874 | constexpr bool __use_const |
2875 | = (__detail::__simple_view<_Vp> | |
2876 | && is_reference_v<range_reference_t<_Vp>>); | |
afb8da7f | 2877 | return _Iterator<__use_const>{this, ranges::begin(_M_base)}; |
cba9ef06 PP |
2878 | } |
2879 | ||
2880 | constexpr auto | |
2881 | begin() const | |
2882 | requires input_range<const _Vp> | |
2883 | && is_reference_v<range_reference_t<const _Vp>> | |
2884 | { | |
afb8da7f | 2885 | return _Iterator<true>{this, ranges::begin(_M_base)}; |
cba9ef06 PP |
2886 | } |
2887 | ||
2888 | constexpr auto | |
2889 | end() | |
2890 | { | |
2891 | if constexpr (forward_range<_Vp> && is_reference_v<_InnerRange> | |
2892 | && forward_range<_InnerRange> | |
2893 | && common_range<_Vp> && common_range<_InnerRange>) | |
afb8da7f | 2894 | return _Iterator<__detail::__simple_view<_Vp>>{this, |
cba9ef06 PP |
2895 | ranges::end(_M_base)}; |
2896 | else | |
afb8da7f | 2897 | return _Sentinel<__detail::__simple_view<_Vp>>{this}; |
cba9ef06 PP |
2898 | } |
2899 | ||
2900 | constexpr auto | |
2901 | end() const | |
2902 | requires input_range<const _Vp> | |
2903 | && is_reference_v<range_reference_t<const _Vp>> | |
2904 | { | |
2905 | if constexpr (forward_range<const _Vp> | |
2906 | && is_reference_v<range_reference_t<const _Vp>> | |
2907 | && forward_range<range_reference_t<const _Vp>> | |
2908 | && common_range<const _Vp> | |
2909 | && common_range<range_reference_t<const _Vp>>) | |
afb8da7f | 2910 | return _Iterator<true>{this, ranges::end(_M_base)}; |
cba9ef06 | 2911 | else |
afb8da7f | 2912 | return _Sentinel<true>{this}; |
cba9ef06 PP |
2913 | } |
2914 | }; | |
2915 | ||
2916 | template<typename _Range> | |
aca60ecf | 2917 | explicit join_view(_Range&&) -> join_view<views::all_t<_Range>>; |
cba9ef06 PP |
2918 | |
2919 | namespace views | |
2920 | { | |
a25321ca PP |
2921 | namespace __detail |
2922 | { | |
2923 | template<typename _Range> | |
2924 | concept __can_join_view | |
2925 | = requires { join_view<all_t<_Range>>{std::declval<_Range>()}; }; | |
2926 | } // namespace __detail | |
2927 | ||
2928 | struct _Join : __adaptor::_RangeAdaptorClosure | |
2929 | { | |
2930 | template<viewable_range _Range> | |
2931 | requires __detail::__can_join_view<_Range> | |
2932 | constexpr auto | |
c8b024fa | 2933 | operator() [[nodiscard]] (_Range&& __r) const |
a25321ca PP |
2934 | { |
2935 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
2936 | // 3474. Nesting join_views is broken because of CTAD | |
2937 | return join_view<all_t<_Range>>{std::forward<_Range>(__r)}; | |
2938 | } | |
57ed620e PP |
2939 | |
2940 | static constexpr bool _S_has_simple_call_op = true; | |
a25321ca PP |
2941 | }; |
2942 | ||
2943 | inline constexpr _Join join; | |
cba9ef06 PP |
2944 | } // namespace views |
2945 | ||
2946 | namespace __detail | |
2947 | { | |
2948 | template<auto> | |
2949 | struct __require_constant; | |
2950 | ||
2951 | template<typename _Range> | |
2952 | concept __tiny_range = sized_range<_Range> | |
2953 | && requires | |
2954 | { typename __require_constant<remove_reference_t<_Range>::size()>; } | |
2955 | && (remove_reference_t<_Range>::size() <= 1); | |
902b40c7 PP |
2956 | |
2957 | template<typename _Base> | |
adbd2c71 | 2958 | struct __lazy_split_view_outer_iter_cat |
902b40c7 PP |
2959 | { }; |
2960 | ||
2961 | template<forward_range _Base> | |
adbd2c71 | 2962 | struct __lazy_split_view_outer_iter_cat<_Base> |
902b40c7 PP |
2963 | { using iterator_category = input_iterator_tag; }; |
2964 | ||
2965 | template<typename _Base> | |
adbd2c71 | 2966 | struct __lazy_split_view_inner_iter_cat |
902b40c7 PP |
2967 | { }; |
2968 | ||
2969 | template<forward_range _Base> | |
adbd2c71 | 2970 | struct __lazy_split_view_inner_iter_cat<_Base> |
902b40c7 PP |
2971 | { |
2972 | private: | |
2973 | static constexpr auto | |
2974 | _S_iter_cat() | |
2975 | { | |
2976 | using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; | |
2977 | if constexpr (derived_from<_Cat, forward_iterator_tag>) | |
2978 | return forward_iterator_tag{}; | |
2979 | else | |
2980 | return _Cat{}; | |
2981 | } | |
2982 | public: | |
2983 | using iterator_category = decltype(_S_iter_cat()); | |
2984 | }; | |
cba9ef06 PP |
2985 | } |
2986 | ||
2987 | template<input_range _Vp, forward_range _Pattern> | |
2988 | requires view<_Vp> && view<_Pattern> | |
2989 | && indirectly_comparable<iterator_t<_Vp>, iterator_t<_Pattern>, | |
2990 | ranges::equal_to> | |
2991 | && (forward_range<_Vp> || __detail::__tiny_range<_Pattern>) | |
adbd2c71 | 2992 | class lazy_split_view : public view_interface<lazy_split_view<_Vp, _Pattern>> |
cba9ef06 PP |
2993 | { |
2994 | private: | |
902b40c7 PP |
2995 | template<bool _Const> |
2996 | using _Base = __detail::__maybe_const_t<_Const, _Vp>; | |
2997 | ||
cba9ef06 PP |
2998 | template<bool _Const> |
2999 | struct _InnerIter; | |
3000 | ||
3001 | template<bool _Const> | |
3002 | struct _OuterIter | |
adbd2c71 | 3003 | : __detail::__lazy_split_view_outer_iter_cat<_Base<_Const>> |
cba9ef06 PP |
3004 | { |
3005 | private: | |
adbd2c71 PP |
3006 | using _Parent = __detail::__maybe_const_t<_Const, lazy_split_view>; |
3007 | using _Base = lazy_split_view::_Base<_Const>; | |
cba9ef06 PP |
3008 | |
3009 | constexpr bool | |
3010 | __at_end() const | |
3f631671 | 3011 | { return __current() == ranges::end(_M_parent->_M_base) && !_M_trailing_empty; } |
cba9ef06 | 3012 | |
adbd2c71 | 3013 | // [range.lazy.split.outer] p1 |
cba9ef06 | 3014 | // Many of the following specifications refer to the notional member |
97a7c229 JW |
3015 | // current of outer-iterator. current is equivalent to current_ if |
3016 | // V models forward_range, and parent_->current_ otherwise. | |
cba9ef06 | 3017 | constexpr auto& |
cf0c3a45 | 3018 | __current() noexcept |
cba9ef06 PP |
3019 | { |
3020 | if constexpr (forward_range<_Vp>) | |
3021 | return _M_current; | |
3022 | else | |
4b4f5666 | 3023 | return *_M_parent->_M_current; |
cba9ef06 PP |
3024 | } |
3025 | ||
3026 | constexpr auto& | |
cf0c3a45 | 3027 | __current() const noexcept |
cba9ef06 PP |
3028 | { |
3029 | if constexpr (forward_range<_Vp>) | |
3030 | return _M_current; | |
3031 | else | |
4b4f5666 | 3032 | return *_M_parent->_M_current; |
cba9ef06 PP |
3033 | } |
3034 | ||
3035 | _Parent* _M_parent = nullptr; | |
3036 | ||
3037 | // XXX: _M_current is present only if "V models forward_range" | |
3038 | [[no_unique_address]] | |
4c391563 JW |
3039 | __detail::__maybe_present_t<forward_range<_Vp>, |
3040 | iterator_t<_Base>> _M_current; | |
3f631671 | 3041 | bool _M_trailing_empty = false; |
cba9ef06 PP |
3042 | |
3043 | public: | |
a09bb4a8 JW |
3044 | using iterator_concept = __conditional_t<forward_range<_Base>, |
3045 | forward_iterator_tag, | |
3046 | input_iterator_tag>; | |
adbd2c71 | 3047 | // iterator_category defined in __lazy_split_view_outer_iter_cat |
cba9ef06 PP |
3048 | using difference_type = range_difference_t<_Base>; |
3049 | ||
3050 | struct value_type : view_interface<value_type> | |
3051 | { | |
3052 | private: | |
3053 | _OuterIter _M_i = _OuterIter(); | |
3054 | ||
3055 | public: | |
3056 | value_type() = default; | |
3057 | ||
3058 | constexpr explicit | |
3059 | value_type(_OuterIter __i) | |
3060 | : _M_i(std::move(__i)) | |
3061 | { } | |
3062 | ||
3063 | constexpr _InnerIter<_Const> | |
3064 | begin() const | |
cba9ef06 PP |
3065 | { return _InnerIter<_Const>{_M_i}; } |
3066 | ||
cba9ef06 PP |
3067 | constexpr default_sentinel_t |
3068 | end() const | |
3069 | { return default_sentinel; } | |
3070 | }; | |
3071 | ||
3072 | _OuterIter() = default; | |
3073 | ||
3074 | constexpr explicit | |
afb8da7f PP |
3075 | _OuterIter(_Parent* __parent) requires (!forward_range<_Base>) |
3076 | : _M_parent(__parent) | |
cba9ef06 PP |
3077 | { } |
3078 | ||
3079 | constexpr | |
afb8da7f | 3080 | _OuterIter(_Parent* __parent, iterator_t<_Base> __current) |
cba9ef06 | 3081 | requires forward_range<_Base> |
afb8da7f | 3082 | : _M_parent(__parent), |
cba9ef06 PP |
3083 | _M_current(std::move(__current)) |
3084 | { } | |
3085 | ||
3086 | constexpr | |
3087 | _OuterIter(_OuterIter<!_Const> __i) | |
3088 | requires _Const | |
242b4fb7 | 3089 | && convertible_to<iterator_t<_Vp>, iterator_t<_Base>> |
cba9ef06 PP |
3090 | : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)) |
3091 | { } | |
3092 | ||
3093 | constexpr value_type | |
3094 | operator*() const | |
3095 | { return value_type{*this}; } | |
3096 | ||
3097 | constexpr _OuterIter& | |
3098 | operator++() | |
3099 | { | |
b5242b28 | 3100 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
adbd2c71 | 3101 | // 3505. lazy_split_view::outer-iterator::operator++ misspecified |
cba9ef06 | 3102 | const auto __end = ranges::end(_M_parent->_M_base); |
0b7f1e24 | 3103 | if (__current() == __end) |
3f631671 PP |
3104 | { |
3105 | _M_trailing_empty = false; | |
3106 | return *this; | |
3107 | } | |
cba9ef06 PP |
3108 | const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; |
3109 | if (__pbegin == __pend) | |
0b7f1e24 | 3110 | ++__current(); |
b5242b28 PP |
3111 | else if constexpr (__detail::__tiny_range<_Pattern>) |
3112 | { | |
2786064d PP |
3113 | __current() = ranges::find(std::move(__current()), __end, |
3114 | *__pbegin); | |
b5242b28 | 3115 | if (__current() != __end) |
3f631671 PP |
3116 | { |
3117 | ++__current(); | |
3118 | if (__current() == __end) | |
3119 | _M_trailing_empty = true; | |
3120 | } | |
b5242b28 | 3121 | } |
cba9ef06 PP |
3122 | else |
3123 | do | |
3124 | { | |
3125 | auto [__b, __p] | |
2786064d | 3126 | = ranges::mismatch(__current(), __end, __pbegin, __pend); |
cba9ef06 | 3127 | if (__p == __pend) |
b5242b28 PP |
3128 | { |
3129 | __current() = __b; | |
3f631671 PP |
3130 | if (__current() == __end) |
3131 | _M_trailing_empty = true; | |
b5242b28 PP |
3132 | break; |
3133 | } | |
0b7f1e24 | 3134 | } while (++__current() != __end); |
cba9ef06 PP |
3135 | return *this; |
3136 | } | |
3137 | ||
3138 | constexpr decltype(auto) | |
3139 | operator++(int) | |
3140 | { | |
3141 | if constexpr (forward_range<_Base>) | |
3142 | { | |
3143 | auto __tmp = *this; | |
3144 | ++*this; | |
3145 | return __tmp; | |
3146 | } | |
3147 | else | |
3148 | ++*this; | |
3149 | } | |
3150 | ||
3151 | friend constexpr bool | |
3152 | operator==(const _OuterIter& __x, const _OuterIter& __y) | |
3153 | requires forward_range<_Base> | |
3f631671 PP |
3154 | { |
3155 | return __x._M_current == __y._M_current | |
3156 | && __x._M_trailing_empty == __y._M_trailing_empty; | |
3157 | } | |
cba9ef06 PP |
3158 | |
3159 | friend constexpr bool | |
3160 | operator==(const _OuterIter& __x, default_sentinel_t) | |
3161 | { return __x.__at_end(); }; | |
3162 | ||
ba49e9eb | 3163 | friend _OuterIter<!_Const>; |
cba9ef06 PP |
3164 | friend _InnerIter<_Const>; |
3165 | }; | |
3166 | ||
3167 | template<bool _Const> | |
3168 | struct _InnerIter | |
adbd2c71 | 3169 | : __detail::__lazy_split_view_inner_iter_cat<_Base<_Const>> |
cba9ef06 PP |
3170 | { |
3171 | private: | |
adbd2c71 | 3172 | using _Base = lazy_split_view::_Base<_Const>; |
cba9ef06 PP |
3173 | |
3174 | constexpr bool | |
3175 | __at_end() const | |
3176 | { | |
3177 | auto [__pcur, __pend] = subrange{_M_i._M_parent->_M_pattern}; | |
3178 | auto __end = ranges::end(_M_i._M_parent->_M_base); | |
3179 | if constexpr (__detail::__tiny_range<_Pattern>) | |
3180 | { | |
cf0c3a45 | 3181 | const auto& __cur = _M_i_current(); |
cba9ef06 PP |
3182 | if (__cur == __end) |
3183 | return true; | |
3184 | if (__pcur == __pend) | |
3185 | return _M_incremented; | |
3186 | return *__cur == *__pcur; | |
3187 | } | |
3188 | else | |
3189 | { | |
cf0c3a45 | 3190 | auto __cur = _M_i_current(); |
cba9ef06 PP |
3191 | if (__cur == __end) |
3192 | return true; | |
3193 | if (__pcur == __pend) | |
3194 | return _M_incremented; | |
3195 | do | |
3196 | { | |
3197 | if (*__cur != *__pcur) | |
3198 | return false; | |
3199 | if (++__pcur == __pend) | |
3200 | return true; | |
3201 | } while (++__cur != __end); | |
3202 | return false; | |
3203 | } | |
3204 | } | |
3205 | ||
cf0c3a45 JW |
3206 | constexpr auto& |
3207 | _M_i_current() noexcept | |
3208 | { return _M_i.__current(); } | |
cba9ef06 | 3209 | |
cf0c3a45 JW |
3210 | constexpr auto& |
3211 | _M_i_current() const noexcept | |
3212 | { return _M_i.__current(); } | |
cba9ef06 PP |
3213 | |
3214 | _OuterIter<_Const> _M_i = _OuterIter<_Const>(); | |
3215 | bool _M_incremented = false; | |
3216 | ||
3217 | public: | |
a5b213dd JW |
3218 | using iterator_concept |
3219 | = typename _OuterIter<_Const>::iterator_concept; | |
adbd2c71 | 3220 | // iterator_category defined in __lazy_split_view_inner_iter_cat |
cba9ef06 PP |
3221 | using value_type = range_value_t<_Base>; |
3222 | using difference_type = range_difference_t<_Base>; | |
3223 | ||
3224 | _InnerIter() = default; | |
3225 | ||
3226 | constexpr explicit | |
3227 | _InnerIter(_OuterIter<_Const> __i) | |
3228 | : _M_i(std::move(__i)) | |
3229 | { } | |
3230 | ||
44140571 PP |
3231 | constexpr const iterator_t<_Base>& |
3232 | base() const& noexcept | |
85a594f7 PP |
3233 | { return _M_i_current(); } |
3234 | ||
3235 | constexpr iterator_t<_Base> | |
2d3ac603 | 3236 | base() && requires forward_range<_Vp> |
85a594f7 PP |
3237 | { return std::move(_M_i_current()); } |
3238 | ||
cba9ef06 PP |
3239 | constexpr decltype(auto) |
3240 | operator*() const | |
cf0c3a45 | 3241 | { return *_M_i_current(); } |
cba9ef06 PP |
3242 | |
3243 | constexpr _InnerIter& | |
3244 | operator++() | |
3245 | { | |
3246 | _M_incremented = true; | |
3247 | if constexpr (!forward_range<_Base>) | |
3248 | if constexpr (_Pattern::size() == 0) | |
3249 | return *this; | |
cf0c3a45 | 3250 | ++_M_i_current(); |
cba9ef06 PP |
3251 | return *this; |
3252 | } | |
3253 | ||
3254 | constexpr decltype(auto) | |
3255 | operator++(int) | |
3256 | { | |
71834be5 | 3257 | if constexpr (forward_range<_Base>) |
cba9ef06 PP |
3258 | { |
3259 | auto __tmp = *this; | |
3260 | ++*this; | |
3261 | return __tmp; | |
3262 | } | |
3263 | else | |
3264 | ++*this; | |
3265 | } | |
3266 | ||
3267 | friend constexpr bool | |
3268 | operator==(const _InnerIter& __x, const _InnerIter& __y) | |
3269 | requires forward_range<_Base> | |
8ce13842 | 3270 | { return __x._M_i == __y._M_i; } |
cba9ef06 PP |
3271 | |
3272 | friend constexpr bool | |
3273 | operator==(const _InnerIter& __x, default_sentinel_t) | |
3274 | { return __x.__at_end(); } | |
3275 | ||
3276 | friend constexpr decltype(auto) | |
cf0c3a45 JW |
3277 | iter_move(const _InnerIter& __i) |
3278 | noexcept(noexcept(ranges::iter_move(__i._M_i_current()))) | |
3279 | { return ranges::iter_move(__i._M_i_current()); } | |
cba9ef06 PP |
3280 | |
3281 | friend constexpr void | |
3282 | iter_swap(const _InnerIter& __x, const _InnerIter& __y) | |
cf0c3a45 JW |
3283 | noexcept(noexcept(ranges::iter_swap(__x._M_i_current(), |
3284 | __y._M_i_current()))) | |
cba9ef06 | 3285 | requires indirectly_swappable<iterator_t<_Base>> |
cf0c3a45 | 3286 | { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } |
cba9ef06 PP |
3287 | }; |
3288 | ||
53b1c382 | 3289 | _Vp _M_base = _Vp(); |
cba9ef06 | 3290 | _Pattern _M_pattern = _Pattern(); |
cba9ef06 PP |
3291 | // XXX: _M_current is "present only if !forward_range<V>" |
3292 | [[no_unique_address]] | |
361e32ee | 3293 | __detail::__maybe_present_t<!forward_range<_Vp>, |
4b4f5666 | 3294 | __detail::__non_propagating_cache<iterator_t<_Vp>>> _M_current; |
cba9ef06 PP |
3295 | |
3296 | ||
3297 | public: | |
adbd2c71 PP |
3298 | lazy_split_view() requires (default_initializable<_Vp> |
3299 | && default_initializable<_Pattern>) | |
4b4f5666 | 3300 | = default; |
cba9ef06 PP |
3301 | |
3302 | constexpr | |
adbd2c71 | 3303 | lazy_split_view(_Vp __base, _Pattern __pattern) |
53b1c382 | 3304 | : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) |
cba9ef06 PP |
3305 | { } |
3306 | ||
cba9ef06 | 3307 | template<input_range _Range> |
aca60ecf | 3308 | requires constructible_from<_Vp, views::all_t<_Range>> |
cba9ef06 PP |
3309 | && constructible_from<_Pattern, single_view<range_value_t<_Range>>> |
3310 | constexpr | |
adbd2c71 | 3311 | lazy_split_view(_Range&& __r, range_value_t<_Range> __e) |
53b1c382 PP |
3312 | : _M_base(views::all(std::forward<_Range>(__r))), |
3313 | _M_pattern(views::single(std::move(__e))) | |
cba9ef06 PP |
3314 | { } |
3315 | ||
3316 | constexpr _Vp | |
3317 | base() const& requires copy_constructible<_Vp> | |
3318 | { return _M_base; } | |
3319 | ||
3320 | constexpr _Vp | |
3321 | base() && | |
3322 | { return std::move(_M_base); } | |
3323 | ||
3324 | constexpr auto | |
3325 | begin() | |
3326 | { | |
3327 | if constexpr (forward_range<_Vp>) | |
2d3ac603 PP |
3328 | { |
3329 | constexpr bool __simple | |
3330 | = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; | |
3331 | return _OuterIter<__simple>{this, ranges::begin(_M_base)}; | |
3332 | } | |
cba9ef06 PP |
3333 | else |
3334 | { | |
3335 | _M_current = ranges::begin(_M_base); | |
afb8da7f | 3336 | return _OuterIter<false>{this}; |
cba9ef06 PP |
3337 | } |
3338 | } | |
3339 | ||
3340 | constexpr auto | |
3341 | begin() const requires forward_range<_Vp> && forward_range<const _Vp> | |
3342 | { | |
afb8da7f | 3343 | return _OuterIter<true>{this, ranges::begin(_M_base)}; |
cba9ef06 PP |
3344 | } |
3345 | ||
3346 | constexpr auto | |
3347 | end() requires forward_range<_Vp> && common_range<_Vp> | |
3348 | { | |
2d3ac603 PP |
3349 | constexpr bool __simple |
3350 | = __detail::__simple_view<_Vp> && __detail::__simple_view<_Pattern>; | |
3351 | return _OuterIter<__simple>{this, ranges::end(_M_base)}; | |
cba9ef06 PP |
3352 | } |
3353 | ||
3354 | constexpr auto | |
3355 | end() const | |
3356 | { | |
3357 | if constexpr (forward_range<_Vp> | |
3358 | && forward_range<const _Vp> | |
3359 | && common_range<const _Vp>) | |
afb8da7f | 3360 | return _OuterIter<true>{this, ranges::end(_M_base)}; |
cba9ef06 PP |
3361 | else |
3362 | return default_sentinel; | |
3363 | } | |
3364 | }; | |
3365 | ||
a25321ca | 3366 | template<typename _Range, typename _Pattern> |
adbd2c71 PP |
3367 | lazy_split_view(_Range&&, _Pattern&&) |
3368 | -> lazy_split_view<views::all_t<_Range>, views::all_t<_Pattern>>; | |
cba9ef06 PP |
3369 | |
3370 | template<input_range _Range> | |
adbd2c71 PP |
3371 | lazy_split_view(_Range&&, range_value_t<_Range>) |
3372 | -> lazy_split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; | |
cba9ef06 PP |
3373 | |
3374 | namespace views | |
3375 | { | |
a25321ca PP |
3376 | namespace __detail |
3377 | { | |
3378 | template<typename _Range, typename _Pattern> | |
adbd2c71 PP |
3379 | concept __can_lazy_split_view |
3380 | = requires { lazy_split_view(std::declval<_Range>(), std::declval<_Pattern>()); }; | |
a25321ca PP |
3381 | } // namespace __detail |
3382 | ||
adbd2c71 | 3383 | struct _LazySplit : __adaptor::_RangeAdaptor<_LazySplit> |
a25321ca PP |
3384 | { |
3385 | template<viewable_range _Range, typename _Pattern> | |
adbd2c71 | 3386 | requires __detail::__can_lazy_split_view<_Range, _Pattern> |
a25321ca | 3387 | constexpr auto |
c8b024fa | 3388 | operator() [[nodiscard]] (_Range&& __r, _Pattern&& __f) const |
a25321ca | 3389 | { |
adbd2c71 | 3390 | return lazy_split_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f)); |
a25321ca PP |
3391 | } |
3392 | ||
adbd2c71 | 3393 | using _RangeAdaptor<_LazySplit>::operator(); |
a25321ca | 3394 | static constexpr int _S_arity = 2; |
adbd2c71 | 3395 | // The pattern argument of views::lazy_split is not always simple -- it can be |
0f4a2fb4 PP |
3396 | // a non-view range, the value category of which affects whether the call |
3397 | // is well-formed. But a scalar or a view pattern argument is surely | |
3398 | // simple. | |
3399 | template<typename _Pattern> | |
3400 | static constexpr bool _S_has_simple_extra_args | |
3401 | = is_scalar_v<_Pattern> || (view<_Pattern> | |
3402 | && copy_constructible<_Pattern>); | |
a25321ca PP |
3403 | }; |
3404 | ||
adbd2c71 | 3405 | inline constexpr _LazySplit lazy_split; |
cba9ef06 PP |
3406 | } // namespace views |
3407 | ||
69d80f0f PP |
3408 | template<forward_range _Vp, forward_range _Pattern> |
3409 | requires view<_Vp> && view<_Pattern> | |
3410 | && indirectly_comparable<iterator_t<_Vp>, iterator_t<_Pattern>, | |
3411 | ranges::equal_to> | |
3412 | class split_view : public view_interface<split_view<_Vp, _Pattern>> | |
3413 | { | |
3414 | private: | |
53b1c382 | 3415 | _Vp _M_base = _Vp(); |
69d80f0f PP |
3416 | _Pattern _M_pattern = _Pattern(); |
3417 | __detail::__non_propagating_cache<subrange<iterator_t<_Vp>>> _M_cached_begin; | |
69d80f0f PP |
3418 | |
3419 | struct _Iterator; | |
3420 | struct _Sentinel; | |
3421 | ||
3422 | public: | |
3423 | split_view() requires (default_initializable<_Vp> | |
3424 | && default_initializable<_Pattern>) | |
3425 | = default; | |
3426 | ||
3427 | constexpr | |
3428 | split_view(_Vp __base, _Pattern __pattern) | |
53b1c382 | 3429 | : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) |
69d80f0f PP |
3430 | { } |
3431 | ||
3432 | template<forward_range _Range> | |
3433 | requires constructible_from<_Vp, views::all_t<_Range>> | |
3434 | && constructible_from<_Pattern, single_view<range_value_t<_Range>>> | |
3435 | constexpr | |
3436 | split_view(_Range&& __r, range_value_t<_Range> __e) | |
53b1c382 PP |
3437 | : _M_base(views::all(std::forward<_Range>(__r))), |
3438 | _M_pattern(views::single(std::move(__e))) | |
69d80f0f PP |
3439 | { } |
3440 | ||
3441 | constexpr _Vp | |
2d3ac603 | 3442 | base() const& requires copy_constructible<_Vp> |
69d80f0f PP |
3443 | { return _M_base; } |
3444 | ||
3445 | constexpr _Vp | |
3446 | base() && | |
3447 | { return std::move(_M_base); } | |
3448 | ||
3449 | constexpr _Iterator | |
3450 | begin() | |
3451 | { | |
3452 | if (!_M_cached_begin) | |
3453 | _M_cached_begin = _M_find_next(ranges::begin(_M_base)); | |
3454 | return {this, ranges::begin(_M_base), *_M_cached_begin}; | |
3455 | } | |
3456 | ||
3457 | constexpr auto | |
3458 | end() | |
3459 | { | |
3460 | if constexpr (common_range<_Vp>) | |
3461 | return _Iterator{this, ranges::end(_M_base), {}}; | |
3462 | else | |
3463 | return _Sentinel{this}; | |
3464 | } | |
3465 | ||
3466 | constexpr subrange<iterator_t<_Vp>> | |
3467 | _M_find_next(iterator_t<_Vp> __it) | |
3468 | { | |
3469 | auto [__b, __e] = ranges::search(subrange(__it, ranges::end(_M_base)), _M_pattern); | |
3470 | if (__b != ranges::end(_M_base) && ranges::empty(_M_pattern)) | |
3471 | { | |
3472 | ++__b; | |
3473 | ++__e; | |
3474 | } | |
3475 | return {__b, __e}; | |
3476 | } | |
3477 | ||
3478 | private: | |
3479 | struct _Iterator | |
3480 | { | |
3481 | private: | |
3482 | split_view* _M_parent = nullptr; | |
3483 | iterator_t<_Vp> _M_cur = iterator_t<_Vp>(); | |
3484 | subrange<iterator_t<_Vp>> _M_next = subrange<iterator_t<_Vp>>(); | |
3485 | bool _M_trailing_empty = false; | |
3486 | ||
3487 | friend struct _Sentinel; | |
3488 | ||
3489 | public: | |
3490 | using iterator_concept = forward_iterator_tag; | |
3491 | using iterator_category = input_iterator_tag; | |
3492 | using value_type = subrange<iterator_t<_Vp>>; | |
3493 | using difference_type = range_difference_t<_Vp>; | |
3494 | ||
73464a47 | 3495 | _Iterator() = default; |
69d80f0f PP |
3496 | |
3497 | constexpr | |
3498 | _Iterator(split_view* __parent, | |
3499 | iterator_t<_Vp> __current, | |
3500 | subrange<iterator_t<_Vp>> __next) | |
3501 | : _M_parent(__parent), | |
3502 | _M_cur(std::move(__current)), | |
3503 | _M_next(std::move(__next)) | |
3504 | { } | |
3505 | ||
3506 | constexpr iterator_t<_Vp> | |
3507 | base() const | |
3508 | { return _M_cur; } | |
3509 | ||
3510 | constexpr value_type | |
3511 | operator*() const | |
3512 | { return {_M_cur, _M_next.begin()}; } | |
3513 | ||
3514 | constexpr _Iterator& | |
3515 | operator++() | |
3516 | { | |
3517 | _M_cur = _M_next.begin(); | |
3518 | if (_M_cur != ranges::end(_M_parent->_M_base)) | |
3519 | { | |
3520 | _M_cur = _M_next.end(); | |
3521 | if (_M_cur == ranges::end(_M_parent->_M_base)) | |
3522 | { | |
3523 | _M_trailing_empty = true; | |
3524 | _M_next = {_M_cur, _M_cur}; | |
3525 | } | |
3526 | else | |
3527 | _M_next = _M_parent->_M_find_next(_M_cur); | |
3528 | } | |
3529 | else | |
3530 | _M_trailing_empty = false; | |
3531 | return *this; | |
3532 | } | |
3533 | ||
3534 | constexpr _Iterator | |
3535 | operator++(int) | |
3536 | { | |
3537 | auto __tmp = *this; | |
3538 | ++*this; | |
3539 | return __tmp; | |
3540 | } | |
3541 | ||
3542 | friend constexpr bool | |
3543 | operator==(const _Iterator& __x, const _Iterator& __y) | |
3544 | { | |
3545 | return __x._M_cur == __y._M_cur | |
3546 | && __x._M_trailing_empty == __y._M_trailing_empty; | |
3547 | } | |
3548 | }; | |
3549 | ||
3550 | struct _Sentinel | |
3551 | { | |
3552 | private: | |
3553 | sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); | |
3554 | ||
3555 | constexpr bool | |
3556 | _M_equal(const _Iterator& __x) const | |
3557 | { return __x._M_cur == _M_end && !__x._M_trailing_empty; } | |
3558 | ||
3559 | public: | |
73464a47 PP |
3560 | _Sentinel() = default; |
3561 | ||
69d80f0f PP |
3562 | constexpr explicit |
3563 | _Sentinel(split_view* __parent) | |
3564 | : _M_end(ranges::end(__parent->_M_base)) | |
3565 | { } | |
3566 | ||
3567 | friend constexpr bool | |
3568 | operator==(const _Iterator& __x, const _Sentinel& __y) | |
3569 | { return __y._M_equal(__x); } | |
3570 | }; | |
3571 | }; | |
3572 | ||
3573 | template<typename _Range, typename _Pattern> | |
3574 | split_view(_Range&&, _Pattern&&) | |
3575 | -> split_view<views::all_t<_Range>, views::all_t<_Pattern>>; | |
3576 | ||
3577 | template<forward_range _Range> | |
3578 | split_view(_Range&&, range_value_t<_Range>) | |
3579 | -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>; | |
3580 | ||
3581 | namespace views | |
3582 | { | |
3583 | namespace __detail | |
3584 | { | |
3585 | template<typename _Range, typename _Pattern> | |
3586 | concept __can_split_view | |
3587 | = requires { split_view(std::declval<_Range>(), std::declval<_Pattern>()); }; | |
3588 | } // namespace __detail | |
3589 | ||
3590 | struct _Split : __adaptor::_RangeAdaptor<_Split> | |
3591 | { | |
3592 | template<viewable_range _Range, typename _Pattern> | |
3593 | requires __detail::__can_split_view<_Range, _Pattern> | |
3594 | constexpr auto | |
c8b024fa | 3595 | operator() [[nodiscard]] (_Range&& __r, _Pattern&& __f) const |
69d80f0f PP |
3596 | { |
3597 | return split_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f)); | |
3598 | } | |
3599 | ||
3600 | using _RangeAdaptor<_Split>::operator(); | |
3601 | static constexpr int _S_arity = 2; | |
3602 | template<typename _Pattern> | |
3603 | static constexpr bool _S_has_simple_extra_args | |
3604 | = _LazySplit::_S_has_simple_extra_args<_Pattern>; | |
3605 | }; | |
3606 | ||
3607 | inline constexpr _Split split; | |
3608 | } // namespace views | |
3609 | ||
cba9ef06 PP |
3610 | namespace views |
3611 | { | |
3612 | struct _Counted | |
3613 | { | |
3614 | template<input_or_output_iterator _Iter> | |
3615 | constexpr auto | |
c8b024fa | 3616 | operator() [[nodiscard]] (_Iter __i, iter_difference_t<_Iter> __n) const |
cba9ef06 | 3617 | { |
9626e447 PP |
3618 | if constexpr (contiguous_iterator<_Iter>) |
3619 | return span(std::__to_address(__i), __n); | |
3620 | else if constexpr (random_access_iterator<_Iter>) | |
6e00d9bb | 3621 | return subrange(__i, __i + __n); |
cba9ef06 | 3622 | else |
6e00d9bb PP |
3623 | return subrange(counted_iterator(std::move(__i), __n), |
3624 | default_sentinel); | |
cba9ef06 PP |
3625 | } |
3626 | }; | |
3627 | ||
3628 | inline constexpr _Counted counted{}; | |
3629 | } // namespace views | |
3630 | ||
3631 | template<view _Vp> | |
3632 | requires (!common_range<_Vp>) && copyable<iterator_t<_Vp>> | |
3633 | class common_view : public view_interface<common_view<_Vp>> | |
3634 | { | |
3635 | private: | |
3636 | _Vp _M_base = _Vp(); | |
3637 | ||
3638 | public: | |
4b4f5666 | 3639 | common_view() requires default_initializable<_Vp> = default; |
cba9ef06 PP |
3640 | |
3641 | constexpr explicit | |
3642 | common_view(_Vp __r) | |
3643 | : _M_base(std::move(__r)) | |
3644 | { } | |
3645 | ||
4cc3b275 | 3646 | /* XXX: LWG 3280 didn't remove this constructor, but I think it should? |
cba9ef06 | 3647 | template<viewable_range _Range> |
4cc3b275 | 3648 | requires (!common_range<_Range>) |
aca60ecf | 3649 | && constructible_from<_Vp, views::all_t<_Range>> |
cba9ef06 PP |
3650 | constexpr explicit |
3651 | common_view(_Range&& __r) | |
3652 | : _M_base(views::all(std::forward<_Range>(__r))) | |
3653 | { } | |
4cc3b275 | 3654 | */ |
cba9ef06 PP |
3655 | |
3656 | constexpr _Vp | |
3657 | base() const& requires copy_constructible<_Vp> | |
3658 | { return _M_base; } | |
3659 | ||
3660 | constexpr _Vp | |
3661 | base() && | |
3662 | { return std::move(_M_base); } | |
3663 | ||
3664 | constexpr auto | |
3665 | begin() | |
3666 | { | |
3667 | if constexpr (random_access_range<_Vp> && sized_range<_Vp>) | |
3668 | return ranges::begin(_M_base); | |
3669 | else | |
3670 | return common_iterator<iterator_t<_Vp>, sentinel_t<_Vp>> | |
3671 | (ranges::begin(_M_base)); | |
3672 | } | |
3673 | ||
3674 | constexpr auto | |
3675 | begin() const requires range<const _Vp> | |
3676 | { | |
3677 | if constexpr (random_access_range<const _Vp> && sized_range<const _Vp>) | |
3678 | return ranges::begin(_M_base); | |
3679 | else | |
3680 | return common_iterator<iterator_t<const _Vp>, sentinel_t<const _Vp>> | |
3681 | (ranges::begin(_M_base)); | |
3682 | } | |
3683 | ||
3684 | constexpr auto | |
3685 | end() | |
3686 | { | |
3687 | if constexpr (random_access_range<_Vp> && sized_range<_Vp>) | |
3688 | return ranges::begin(_M_base) + ranges::size(_M_base); | |
3689 | else | |
3690 | return common_iterator<iterator_t<_Vp>, sentinel_t<_Vp>> | |
3691 | (ranges::end(_M_base)); | |
3692 | } | |
3693 | ||
3694 | constexpr auto | |
3695 | end() const requires range<const _Vp> | |
3696 | { | |
3697 | if constexpr (random_access_range<const _Vp> && sized_range<const _Vp>) | |
3698 | return ranges::begin(_M_base) + ranges::size(_M_base); | |
3699 | else | |
3700 | return common_iterator<iterator_t<const _Vp>, sentinel_t<const _Vp>> | |
3701 | (ranges::end(_M_base)); | |
3702 | } | |
3703 | ||
3704 | constexpr auto | |
3705 | size() requires sized_range<_Vp> | |
3706 | { return ranges::size(_M_base); } | |
3707 | ||
3708 | constexpr auto | |
3709 | size() const requires sized_range<const _Vp> | |
3710 | { return ranges::size(_M_base); } | |
3711 | }; | |
3712 | ||
3713 | template<typename _Range> | |
aca60ecf | 3714 | common_view(_Range&&) -> common_view<views::all_t<_Range>>; |
cba9ef06 | 3715 | |
39bf4f14 JW |
3716 | template<typename _Tp> |
3717 | inline constexpr bool enable_borrowed_range<common_view<_Tp>> | |
3718 | = enable_borrowed_range<_Tp>; | |
3719 | ||
cba9ef06 PP |
3720 | namespace views |
3721 | { | |
a25321ca PP |
3722 | namespace __detail |
3723 | { | |
3724 | template<typename _Range> | |
3725 | concept __already_common = common_range<_Range> | |
3726 | && requires { views::all(std::declval<_Range>()); }; | |
3727 | ||
3728 | template<typename _Range> | |
3729 | concept __can_common_view | |
3730 | = requires { common_view{std::declval<_Range>()}; }; | |
3731 | } // namespace __detail | |
3732 | ||
3733 | struct _Common : __adaptor::_RangeAdaptorClosure | |
3734 | { | |
3735 | template<viewable_range _Range> | |
3736 | requires __detail::__already_common<_Range> | |
3737 | || __detail::__can_common_view<_Range> | |
3738 | constexpr auto | |
c8b024fa | 3739 | operator() [[nodiscard]] (_Range&& __r) const |
a25321ca PP |
3740 | { |
3741 | if constexpr (__detail::__already_common<_Range>) | |
3742 | return views::all(std::forward<_Range>(__r)); | |
3743 | else | |
3744 | return common_view{std::forward<_Range>(__r)}; | |
3745 | } | |
57ed620e PP |
3746 | |
3747 | static constexpr bool _S_has_simple_call_op = true; | |
a25321ca | 3748 | }; |
cba9ef06 | 3749 | |
a25321ca | 3750 | inline constexpr _Common common; |
cba9ef06 PP |
3751 | } // namespace views |
3752 | ||
3753 | template<view _Vp> | |
3754 | requires bidirectional_range<_Vp> | |
3755 | class reverse_view : public view_interface<reverse_view<_Vp>> | |
3756 | { | |
3757 | private: | |
77e596cf | 3758 | static constexpr bool _S_needs_cached_begin |
03cf8d54 PP |
3759 | = !common_range<_Vp> && !(random_access_range<_Vp> |
3760 | && sized_sentinel_for<sentinel_t<_Vp>, | |
3761 | iterator_t<_Vp>>); | |
361e32ee | 3762 | |
53b1c382 | 3763 | _Vp _M_base = _Vp(); |
a1535015 | 3764 | [[no_unique_address]] |
4c391563 JW |
3765 | __detail::__maybe_present_t<_S_needs_cached_begin, |
3766 | __detail::_CachedPosition<_Vp>> | |
3767 | _M_cached_begin; | |
a1535015 | 3768 | |
cba9ef06 | 3769 | public: |
4b4f5666 | 3770 | reverse_view() requires default_initializable<_Vp> = default; |
cba9ef06 PP |
3771 | |
3772 | constexpr explicit | |
3773 | reverse_view(_Vp __r) | |
3774 | : _M_base(std::move(__r)) | |
3775 | { } | |
3776 | ||
cba9ef06 PP |
3777 | constexpr _Vp |
3778 | base() const& requires copy_constructible<_Vp> | |
3779 | { return _M_base; } | |
3780 | ||
3781 | constexpr _Vp | |
3782 | base() && | |
3783 | { return std::move(_M_base); } | |
3784 | ||
3785 | constexpr reverse_iterator<iterator_t<_Vp>> | |
3786 | begin() | |
3787 | { | |
a1535015 PP |
3788 | if constexpr (_S_needs_cached_begin) |
3789 | if (_M_cached_begin._M_has_value()) | |
09f08fef | 3790 | return std::make_reverse_iterator(_M_cached_begin._M_get(_M_base)); |
a1535015 PP |
3791 | |
3792 | auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base)); | |
3793 | if constexpr (_S_needs_cached_begin) | |
3794 | _M_cached_begin._M_set(_M_base, __it); | |
09f08fef | 3795 | return std::make_reverse_iterator(std::move(__it)); |
cba9ef06 PP |
3796 | } |
3797 | ||
3798 | constexpr auto | |
3799 | begin() requires common_range<_Vp> | |
09f08fef | 3800 | { return std::make_reverse_iterator(ranges::end(_M_base)); } |
cba9ef06 PP |
3801 | |
3802 | constexpr auto | |
3803 | begin() const requires common_range<const _Vp> | |
09f08fef | 3804 | { return std::make_reverse_iterator(ranges::end(_M_base)); } |
cba9ef06 PP |
3805 | |
3806 | constexpr reverse_iterator<iterator_t<_Vp>> | |
3807 | end() | |
09f08fef | 3808 | { return std::make_reverse_iterator(ranges::begin(_M_base)); } |
cba9ef06 PP |
3809 | |
3810 | constexpr auto | |
3811 | end() const requires common_range<const _Vp> | |
09f08fef | 3812 | { return std::make_reverse_iterator(ranges::begin(_M_base)); } |
cba9ef06 PP |
3813 | |
3814 | constexpr auto | |
3815 | size() requires sized_range<_Vp> | |
3816 | { return ranges::size(_M_base); } | |
3817 | ||
3818 | constexpr auto | |
3819 | size() const requires sized_range<const _Vp> | |
3820 | { return ranges::size(_M_base); } | |
3821 | }; | |
3822 | ||
3823 | template<typename _Range> | |
aca60ecf | 3824 | reverse_view(_Range&&) -> reverse_view<views::all_t<_Range>>; |
cba9ef06 | 3825 | |
39bf4f14 JW |
3826 | template<typename _Tp> |
3827 | inline constexpr bool enable_borrowed_range<reverse_view<_Tp>> | |
3828 | = enable_borrowed_range<_Tp>; | |
3829 | ||
cba9ef06 PP |
3830 | namespace views |
3831 | { | |
3832 | namespace __detail | |
3833 | { | |
3834 | template<typename> | |
3835 | inline constexpr bool __is_reversible_subrange = false; | |
3836 | ||
3837 | template<typename _Iter, subrange_kind _Kind> | |
3838 | inline constexpr bool | |
3839 | __is_reversible_subrange<subrange<reverse_iterator<_Iter>, | |
3840 | reverse_iterator<_Iter>, | |
3841 | _Kind>> = true; | |
3842 | ||
3843 | template<typename> | |
3844 | inline constexpr bool __is_reverse_view = false; | |
3845 | ||
3846 | template<typename _Vp> | |
3847 | inline constexpr bool __is_reverse_view<reverse_view<_Vp>> = true; | |
cba9ef06 | 3848 | |
a25321ca PP |
3849 | template<typename _Range> |
3850 | concept __can_reverse_view | |
3851 | = requires { reverse_view{std::declval<_Range>()}; }; | |
3852 | } // namespace __detail | |
3853 | ||
3854 | struct _Reverse : __adaptor::_RangeAdaptorClosure | |
3855 | { | |
3856 | template<viewable_range _Range> | |
3857 | requires __detail::__is_reverse_view<remove_cvref_t<_Range>> | |
3858 | || __detail::__is_reversible_subrange<remove_cvref_t<_Range>> | |
3859 | || __detail::__can_reverse_view<_Range> | |
3860 | constexpr auto | |
c8b024fa | 3861 | operator() [[nodiscard]] (_Range&& __r) const |
a25321ca PP |
3862 | { |
3863 | using _Tp = remove_cvref_t<_Range>; | |
3864 | if constexpr (__detail::__is_reverse_view<_Tp>) | |
3865 | return std::forward<_Range>(__r).base(); | |
3866 | else if constexpr (__detail::__is_reversible_subrange<_Tp>) | |
3867 | { | |
3868 | using _Iter = decltype(ranges::begin(__r).base()); | |
3869 | if constexpr (sized_range<_Tp>) | |
3870 | return subrange<_Iter, _Iter, subrange_kind::sized> | |
3871 | {__r.end().base(), __r.begin().base(), __r.size()}; | |
3872 | else | |
3873 | return subrange<_Iter, _Iter, subrange_kind::unsized> | |
3874 | {__r.end().base(), __r.begin().base()}; | |
3875 | } | |
3876 | else | |
3877 | return reverse_view{std::forward<_Range>(__r)}; | |
3878 | } | |
57ed620e PP |
3879 | |
3880 | static constexpr bool _S_has_simple_call_op = true; | |
a25321ca PP |
3881 | }; |
3882 | ||
3883 | inline constexpr _Reverse reverse; | |
cba9ef06 PP |
3884 | } // namespace views |
3885 | ||
3886 | namespace __detail | |
3887 | { | |
3888 | template<typename _Tp, size_t _Nm> | |
3889 | concept __has_tuple_element = requires(_Tp __t) | |
3890 | { | |
3891 | typename tuple_size<_Tp>::type; | |
3892 | requires _Nm < tuple_size_v<_Tp>; | |
3893 | typename tuple_element_t<_Nm, _Tp>; | |
cba9ef06 PP |
3894 | { std::get<_Nm>(__t) } |
3895 | -> convertible_to<const tuple_element_t<_Nm, _Tp>&>; | |
3896 | }; | |
c7fe68f3 PP |
3897 | |
3898 | template<typename _Tp, size_t _Nm> | |
3899 | concept __returnable_element | |
3900 | = is_reference_v<_Tp> || move_constructible<tuple_element_t<_Nm, _Tp>>; | |
cba9ef06 PP |
3901 | } |
3902 | ||
3903 | template<input_range _Vp, size_t _Nm> | |
3904 | requires view<_Vp> | |
3905 | && __detail::__has_tuple_element<range_value_t<_Vp>, _Nm> | |
3906 | && __detail::__has_tuple_element<remove_reference_t<range_reference_t<_Vp>>, | |
3907 | _Nm> | |
c7fe68f3 | 3908 | && __detail::__returnable_element<range_reference_t<_Vp>, _Nm> |
cba9ef06 PP |
3909 | class elements_view : public view_interface<elements_view<_Vp, _Nm>> |
3910 | { | |
3911 | public: | |
4b4f5666 | 3912 | elements_view() requires default_initializable<_Vp> = default; |
cba9ef06 PP |
3913 | |
3914 | constexpr explicit | |
3915 | elements_view(_Vp base) | |
3916 | : _M_base(std::move(base)) | |
3917 | { } | |
3918 | ||
44140571 PP |
3919 | constexpr _Vp |
3920 | base() const& requires copy_constructible<_Vp> | |
cba9ef06 PP |
3921 | { return _M_base; } |
3922 | ||
3923 | constexpr _Vp | |
3924 | base() && | |
3925 | { return std::move(_M_base); } | |
3926 | ||
3927 | constexpr auto | |
3928 | begin() requires (!__detail::__simple_view<_Vp>) | |
3929 | { return _Iterator<false>(ranges::begin(_M_base)); } | |
3930 | ||
3931 | constexpr auto | |
4be16d1c | 3932 | begin() const requires range<const _Vp> |
cba9ef06 PP |
3933 | { return _Iterator<true>(ranges::begin(_M_base)); } |
3934 | ||
3935 | constexpr auto | |
4be16d1c | 3936 | end() requires (!__detail::__simple_view<_Vp> && !common_range<_Vp>) |
97ab5daa | 3937 | { return _Sentinel<false>{ranges::end(_M_base)}; } |
cba9ef06 PP |
3938 | |
3939 | constexpr auto | |
4be16d1c | 3940 | end() requires (!__detail::__simple_view<_Vp> && common_range<_Vp>) |
97ab5daa PP |
3941 | { return _Iterator<false>{ranges::end(_M_base)}; } |
3942 | ||
3943 | constexpr auto | |
3944 | end() const requires range<const _Vp> | |
3945 | { return _Sentinel<true>{ranges::end(_M_base)}; } | |
3946 | ||
3947 | constexpr auto | |
3948 | end() const requires common_range<const _Vp> | |
3949 | { return _Iterator<true>{ranges::end(_M_base)}; } | |
cba9ef06 PP |
3950 | |
3951 | constexpr auto | |
3952 | size() requires sized_range<_Vp> | |
3953 | { return ranges::size(_M_base); } | |
3954 | ||
3955 | constexpr auto | |
3956 | size() const requires sized_range<const _Vp> | |
3957 | { return ranges::size(_M_base); } | |
3958 | ||
3959 | private: | |
902b40c7 PP |
3960 | template<bool _Const> |
3961 | using _Base = __detail::__maybe_const_t<_Const, _Vp>; | |
3962 | ||
3963 | template<bool _Const> | |
3964 | struct __iter_cat | |
3965 | { }; | |
3966 | ||
3967 | template<bool _Const> | |
3968 | requires forward_range<_Base<_Const>> | |
3969 | struct __iter_cat<_Const> | |
3970 | { | |
3971 | private: | |
3972 | static auto _S_iter_cat() | |
3973 | { | |
3974 | using _Base = elements_view::_Base<_Const>; | |
5e2e15f2 | 3975 | using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category; |
902b40c7 PP |
3976 | using _Res = decltype((std::get<_Nm>(*std::declval<iterator_t<_Base>>()))); |
3977 | if constexpr (!is_lvalue_reference_v<_Res>) | |
3978 | return input_iterator_tag{}; | |
3979 | else if constexpr (derived_from<_Cat, random_access_iterator_tag>) | |
3980 | return random_access_iterator_tag{}; | |
3981 | else | |
3982 | return _Cat{}; | |
3983 | } | |
3984 | public: | |
3985 | using iterator_category = decltype(_S_iter_cat()); | |
3986 | }; | |
3987 | ||
97ab5daa PP |
3988 | template<bool _Const> |
3989 | struct _Sentinel; | |
3990 | ||
cba9ef06 | 3991 | template<bool _Const> |
902b40c7 | 3992 | struct _Iterator : __iter_cat<_Const> |
cba9ef06 | 3993 | { |
c7fe68f3 | 3994 | private: |
902b40c7 | 3995 | using _Base = elements_view::_Base<_Const>; |
cba9ef06 | 3996 | |
7433536b | 3997 | iterator_t<_Base> _M_current = iterator_t<_Base>(); |
cba9ef06 | 3998 | |
c7fe68f3 PP |
3999 | static constexpr decltype(auto) |
4000 | _S_get_element(const iterator_t<_Base>& __i) | |
4001 | { | |
4002 | if constexpr (is_reference_v<range_reference_t<_Base>>) | |
4003 | return std::get<_Nm>(*__i); | |
4004 | else | |
4005 | { | |
4006 | using _Et = remove_cv_t<tuple_element_t<_Nm, range_reference_t<_Base>>>; | |
4007 | return static_cast<_Et>(std::get<_Nm>(*__i)); | |
4008 | } | |
4009 | } | |
4010 | ||
902b40c7 PP |
4011 | static auto |
4012 | _S_iter_concept() | |
4013 | { | |
bc046a60 | 4014 | if constexpr (random_access_range<_Base>) |
902b40c7 | 4015 | return random_access_iterator_tag{}; |
bc046a60 | 4016 | else if constexpr (bidirectional_range<_Base>) |
902b40c7 | 4017 | return bidirectional_iterator_tag{}; |
bc046a60 | 4018 | else if constexpr (forward_range<_Base>) |
902b40c7 PP |
4019 | return forward_iterator_tag{}; |
4020 | else | |
4021 | return input_iterator_tag{}; | |
4022 | } | |
4023 | ||
cba9ef06 PP |
4024 | friend _Iterator<!_Const>; |
4025 | ||
4026 | public: | |
902b40c7 PP |
4027 | using iterator_concept = decltype(_S_iter_concept()); |
4028 | // iterator_category defined in elements_view::__iter_cat | |
cba9ef06 PP |
4029 | using value_type |
4030 | = remove_cvref_t<tuple_element_t<_Nm, range_value_t<_Base>>>; | |
4031 | using difference_type = range_difference_t<_Base>; | |
4032 | ||
4b4f5666 | 4033 | _Iterator() requires default_initializable<iterator_t<_Base>> = default; |
cba9ef06 PP |
4034 | |
4035 | constexpr explicit | |
4036 | _Iterator(iterator_t<_Base> current) | |
4037 | : _M_current(std::move(current)) | |
4038 | { } | |
4039 | ||
4040 | constexpr | |
4041 | _Iterator(_Iterator<!_Const> i) | |
4042 | requires _Const && convertible_to<iterator_t<_Vp>, iterator_t<_Base>> | |
4043 | : _M_current(std::move(i._M_current)) | |
4044 | { } | |
4045 | ||
44140571 PP |
4046 | constexpr const iterator_t<_Base>& |
4047 | base() const& noexcept | |
cba9ef06 PP |
4048 | { return _M_current; } |
4049 | ||
4050 | constexpr iterator_t<_Base> | |
4051 | base() && | |
4052 | { return std::move(_M_current); } | |
4053 | ||
4054 | constexpr decltype(auto) | |
c7fe68f3 PP |
4055 | operator*() const |
4056 | { return _S_get_element(_M_current); } | |
cba9ef06 PP |
4057 | |
4058 | constexpr _Iterator& | |
4059 | operator++() | |
4060 | { | |
4061 | ++_M_current; | |
4062 | return *this; | |
4063 | } | |
4064 | ||
4065 | constexpr void | |
c7fe68f3 | 4066 | operator++(int) |
cba9ef06 PP |
4067 | { ++_M_current; } |
4068 | ||
4069 | constexpr _Iterator | |
4070 | operator++(int) requires forward_range<_Base> | |
4071 | { | |
4072 | auto __tmp = *this; | |
4073 | ++_M_current; | |
4074 | return __tmp; | |
4075 | } | |
4076 | ||
4077 | constexpr _Iterator& | |
4078 | operator--() requires bidirectional_range<_Base> | |
4079 | { | |
4080 | --_M_current; | |
4081 | return *this; | |
4082 | } | |
4083 | ||
4084 | constexpr _Iterator | |
4085 | operator--(int) requires bidirectional_range<_Base> | |
4086 | { | |
4087 | auto __tmp = *this; | |
4088 | --_M_current; | |
4089 | return __tmp; | |
4090 | } | |
4091 | ||
4092 | constexpr _Iterator& | |
4093 | operator+=(difference_type __n) | |
4094 | requires random_access_range<_Base> | |
4095 | { | |
4096 | _M_current += __n; | |
4097 | return *this; | |
4098 | } | |
4099 | ||
4100 | constexpr _Iterator& | |
4101 | operator-=(difference_type __n) | |
4102 | requires random_access_range<_Base> | |
4103 | { | |
4104 | _M_current -= __n; | |
4105 | return *this; | |
4106 | } | |
4107 | ||
4108 | constexpr decltype(auto) | |
4109 | operator[](difference_type __n) const | |
4110 | requires random_access_range<_Base> | |
c7fe68f3 | 4111 | { return _S_get_element(_M_current + __n); } |
cba9ef06 PP |
4112 | |
4113 | friend constexpr bool | |
4114 | operator==(const _Iterator& __x, const _Iterator& __y) | |
4115 | requires equality_comparable<iterator_t<_Base>> | |
4116 | { return __x._M_current == __y._M_current; } | |
4117 | ||
cba9ef06 PP |
4118 | friend constexpr bool |
4119 | operator<(const _Iterator& __x, const _Iterator& __y) | |
4120 | requires random_access_range<_Base> | |
4121 | { return __x._M_current < __y._M_current; } | |
4122 | ||
4123 | friend constexpr bool | |
4124 | operator>(const _Iterator& __x, const _Iterator& __y) | |
4125 | requires random_access_range<_Base> | |
4126 | { return __y._M_current < __x._M_current; } | |
4127 | ||
4128 | friend constexpr bool | |
4129 | operator<=(const _Iterator& __x, const _Iterator& __y) | |
4130 | requires random_access_range<_Base> | |
4131 | { return !(__y._M_current > __x._M_current); } | |
4132 | ||
4133 | friend constexpr bool | |
4134 | operator>=(const _Iterator& __x, const _Iterator& __y) | |
4135 | requires random_access_range<_Base> | |
4136 | { return !(__x._M_current > __y._M_current); } | |
4137 | ||
4138 | #ifdef __cpp_lib_three_way_comparison | |
4139 | friend constexpr auto | |
4140 | operator<=>(const _Iterator& __x, const _Iterator& __y) | |
4141 | requires random_access_range<_Base> | |
4142 | && three_way_comparable<iterator_t<_Base>> | |
4143 | { return __x._M_current <=> __y._M_current; } | |
4144 | #endif | |
4145 | ||
4146 | friend constexpr _Iterator | |
4147 | operator+(const _Iterator& __x, difference_type __y) | |
4148 | requires random_access_range<_Base> | |
4149 | { return _Iterator{__x} += __y; } | |
4150 | ||
4151 | friend constexpr _Iterator | |
4152 | operator+(difference_type __x, const _Iterator& __y) | |
4153 | requires random_access_range<_Base> | |
4154 | { return __y + __x; } | |
4155 | ||
4156 | friend constexpr _Iterator | |
4157 | operator-(const _Iterator& __x, difference_type __y) | |
4158 | requires random_access_range<_Base> | |
4159 | { return _Iterator{__x} -= __y; } | |
4160 | ||
2ec58cfc JW |
4161 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
4162 | // 3483. transform_view::iterator's difference is overconstrained | |
cba9ef06 PP |
4163 | friend constexpr difference_type |
4164 | operator-(const _Iterator& __x, const _Iterator& __y) | |
2ec58cfc | 4165 | requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> |
cba9ef06 PP |
4166 | { return __x._M_current - __y._M_current; } |
4167 | ||
2e2eef80 | 4168 | template <bool> friend struct _Sentinel; |
97ab5daa PP |
4169 | }; |
4170 | ||
4171 | template<bool _Const> | |
4172 | struct _Sentinel | |
4173 | { | |
4174 | private: | |
2e2eef80 PP |
4175 | template<bool _Const2> |
4176 | constexpr bool | |
4177 | _M_equal(const _Iterator<_Const2>& __x) const | |
4178 | { return __x._M_current == _M_end; } | |
4179 | ||
4180 | template<bool _Const2> | |
4181 | constexpr auto | |
4182 | _M_distance_from(const _Iterator<_Const2>& __i) const | |
4183 | { return _M_end - __i._M_current; } | |
97ab5daa | 4184 | |
902b40c7 | 4185 | using _Base = elements_view::_Base<_Const>; |
97ab5daa PP |
4186 | sentinel_t<_Base> _M_end = sentinel_t<_Base>(); |
4187 | ||
4188 | public: | |
4189 | _Sentinel() = default; | |
4190 | ||
4191 | constexpr explicit | |
4192 | _Sentinel(sentinel_t<_Base> __end) | |
4193 | : _M_end(std::move(__end)) | |
4194 | { } | |
4195 | ||
4196 | constexpr | |
4197 | _Sentinel(_Sentinel<!_Const> __other) | |
4198 | requires _Const | |
4199 | && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>> | |
4200 | : _M_end(std::move(__other._M_end)) | |
4201 | { } | |
4202 | ||
4203 | constexpr sentinel_t<_Base> | |
4204 | base() const | |
4205 | { return _M_end; } | |
4206 | ||
4be16d1c PP |
4207 | template<bool _Const2> |
4208 | requires sentinel_for<sentinel_t<_Base>, | |
4209 | iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> | |
4210 | friend constexpr bool | |
4211 | operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) | |
4212 | { return __y._M_equal(__x); } | |
4213 | ||
4214 | template<bool _Const2, | |
4215 | typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>> | |
4216 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>> | |
4217 | friend constexpr range_difference_t<_Base2> | |
4218 | operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) | |
38751c4d | 4219 | { return -__y._M_distance_from(__x); } |
4be16d1c PP |
4220 | |
4221 | template<bool _Const2, | |
4222 | typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>> | |
4223 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>> | |
2e2eef80 | 4224 | friend constexpr range_difference_t<_Base2> |
4be16d1c | 4225 | operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y) |
2e2eef80 | 4226 | { return __x._M_distance_from(__y); } |
97ab5daa PP |
4227 | |
4228 | friend _Sentinel<!_Const>; | |
cba9ef06 PP |
4229 | }; |
4230 | ||
4231 | _Vp _M_base = _Vp(); | |
4232 | }; | |
4233 | ||
39bf4f14 JW |
4234 | template<typename _Tp, size_t _Nm> |
4235 | inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Nm>> | |
4236 | = enable_borrowed_range<_Tp>; | |
4237 | ||
cba9ef06 | 4238 | template<typename _Range> |
aca60ecf | 4239 | using keys_view = elements_view<views::all_t<_Range>, 0>; |
cba9ef06 PP |
4240 | |
4241 | template<typename _Range> | |
aca60ecf | 4242 | using values_view = elements_view<views::all_t<_Range>, 1>; |
cba9ef06 PP |
4243 | |
4244 | namespace views | |
4245 | { | |
a25321ca PP |
4246 | namespace __detail |
4247 | { | |
4248 | template<size_t _Nm, typename _Range> | |
4249 | concept __can_elements_view | |
4250 | = requires { elements_view<all_t<_Range>, _Nm>{std::declval<_Range>()}; }; | |
4251 | } // namespace __detail | |
4252 | ||
cba9ef06 | 4253 | template<size_t _Nm> |
a25321ca | 4254 | struct _Elements : __adaptor::_RangeAdaptorClosure |
cba9ef06 | 4255 | { |
a25321ca PP |
4256 | template<viewable_range _Range> |
4257 | requires __detail::__can_elements_view<_Nm, _Range> | |
4258 | constexpr auto | |
c8b024fa | 4259 | operator() [[nodiscard]] (_Range&& __r) const |
a25321ca PP |
4260 | { |
4261 | return elements_view<all_t<_Range>, _Nm>{std::forward<_Range>(__r)}; | |
4262 | } | |
57ed620e PP |
4263 | |
4264 | static constexpr bool _S_has_simple_call_op = true; | |
cba9ef06 PP |
4265 | }; |
4266 | ||
a25321ca PP |
4267 | template<size_t _Nm> |
4268 | inline constexpr _Elements<_Nm> elements; | |
4269 | inline constexpr auto keys = elements<0>; | |
4270 | inline constexpr auto values = elements<1>; | |
cba9ef06 PP |
4271 | } // namespace views |
4272 | ||
4273 | } // namespace ranges | |
4274 | ||
4275 | namespace views = ranges::views; | |
4276 | ||
328b52d6 JW |
4277 | _GLIBCXX_END_NAMESPACE_VERSION |
4278 | } // namespace | |
4279 | #endif // library concepts | |
4280 | #endif // C++2a | |
4281 | #endif /* _GLIBCXX_RANGES */ |