]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/ranges
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / ranges
CommitLineData
328b52d6
JW
1// <ranges> -*- C++ -*-
2
99dee823 3// Copyright (C) 2019-2021 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>
cba9ef06 45#include <tuple>
160061ac
JW
46#include <bits/ranges_util.h>
47#include <bits/refwrap.h>
328b52d6
JW
48
49/**
50 * @defgroup ranges Ranges
51 *
52 * Components for dealing with ranges of elements.
53 */
54
55namespace std _GLIBCXX_VISIBILITY(default)
56{
57_GLIBCXX_BEGIN_NAMESPACE_VERSION
58namespace ranges
59{
160061ac
JW
60 // [range.access] customization point objects
61 // [range.req] range and view concepts
62 // [range.dangling] dangling iterator handling
63 // Defined in <bits/ranges_base.h>
37f33df7 64
160061ac
JW
65 // [view.interface] View interface
66 // [range.subrange] Sub-ranges
67 // Defined in <bits/ranges_util.h>
37f33df7 68
160061ac 69 // C++20 24.6 [range.factories] Range factories
b5b2e387 70
160061ac 71 /// A view that contains no elements.
37f33df7 72 template<typename _Tp> requires is_object_v<_Tp>
b5b2e387
JW
73 class empty_view
74 : public view_interface<empty_view<_Tp>>
37f33df7
JW
75 {
76 public:
77 static constexpr _Tp* begin() noexcept { return nullptr; }
78 static constexpr _Tp* end() noexcept { return nullptr; }
79 static constexpr _Tp* data() noexcept { return nullptr; }
80 static constexpr size_t size() noexcept { return 0; }
81 static constexpr bool empty() noexcept { return true; }
37f33df7
JW
82 };
83
b5b2e387 84 template<typename _Tp>
15411a64 85 inline constexpr bool enable_borrowed_range<empty_view<_Tp>> = true;
b5b2e387 86
37f33df7
JW
87 namespace __detail
88 {
42907ca9
PP
89 template<typename _Tp>
90 concept __boxable = copy_constructible<_Tp> && is_object_v<_Tp>;
91
92 template<__boxable _Tp>
37f33df7
JW
93 struct __box : std::optional<_Tp>
94 {
95 using std::optional<_Tp>::optional;
96
97 constexpr
98 __box()
99 noexcept(is_nothrow_default_constructible_v<_Tp>)
100 requires default_initializable<_Tp>
101 : std::optional<_Tp>{std::in_place}
102 { }
103
cba9ef06
PP
104 __box(const __box&) = default;
105 __box(__box&&) = default;
106
37f33df7
JW
107 using std::optional<_Tp>::operator=;
108
00ffe730
JW
109 // _GLIBCXX_RESOLVE_LIB_DEFECTS
110 // 3477. Simplify constraints for semiregular-box
37f33df7
JW
111 __box&
112 operator=(const __box& __that)
113 noexcept(is_nothrow_copy_constructible_v<_Tp>)
00ffe730 114 requires (!copyable<_Tp>)
37f33df7
JW
115 {
116 if ((bool)__that)
117 this->emplace(*__that);
118 else
119 this->reset();
120 return *this;
121 }
122
123 __box&
124 operator=(__box&& __that)
125 noexcept(is_nothrow_move_constructible_v<_Tp>)
00ffe730 126 requires (!movable<_Tp>)
37f33df7
JW
127 {
128 if ((bool)__that)
129 this->emplace(std::move(*__that));
130 else
131 this->reset();
132 return *this;
133 }
134 };
135
42907ca9
PP
136 // For types which are already semiregular, this specialization of the
137 // semiregular wrapper stores the object directly without going through
138 // std::optional. It provides just the subset of the primary template's
139 // API that we currently use.
140 template<__boxable _Tp> requires semiregular<_Tp>
141 struct __box<_Tp>
142 {
143 private:
f3ced677 144 [[no_unique_address]] _Tp _M_value = _Tp();
42907ca9
PP
145
146 public:
147 __box() = default;
148
149 constexpr explicit
150 __box(const _Tp& __t)
151 noexcept(is_nothrow_copy_constructible_v<_Tp>)
152 : _M_value{__t}
153 { }
154
155 constexpr explicit
156 __box(_Tp&& __t)
157 noexcept(is_nothrow_move_constructible_v<_Tp>)
158 : _M_value{std::move(__t)}
159 { }
160
161 template<typename... _Args>
162 requires constructible_from<_Tp, _Args...>
f3ced677 163 constexpr explicit
42907ca9
PP
164 __box(in_place_t, _Args&&... __args)
165 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
166 : _M_value{std::forward<_Args>(__args)...}
167 { }
168
169 constexpr bool
170 has_value() const noexcept
171 { return true; };
172
173 constexpr _Tp&
174 operator*() noexcept
175 { return _M_value; }
176
177 constexpr const _Tp&
178 operator*() const noexcept
179 { return _M_value; }
180
181 constexpr _Tp*
182 operator->() noexcept
183 { return &_M_value; }
184
185 constexpr const _Tp*
186 operator->() const noexcept
187 { return &_M_value; }
188 };
37f33df7
JW
189 } // namespace __detail
190
191 /// A view that contains exactly one element.
192 template<copy_constructible _Tp> requires is_object_v<_Tp>
193 class single_view : public view_interface<single_view<_Tp>>
194 {
195 public:
196 single_view() = default;
197
198 constexpr explicit
199 single_view(const _Tp& __t)
200 : _M_value(__t)
201 { }
202
203 constexpr explicit
204 single_view(_Tp&& __t)
205 : _M_value(std::move(__t))
206 { }
207
50106208
PP
208 // _GLIBCXX_RESOLVE_LIB_DEFECTS
209 // 3428. single_view's in place constructor should be explicit
37f33df7
JW
210 template<typename... _Args>
211 requires constructible_from<_Tp, _Args...>
50106208 212 constexpr explicit
37f33df7
JW
213 single_view(in_place_t, _Args&&... __args)
214 : _M_value{in_place, std::forward<_Args>(__args)...}
215 { }
216
217 constexpr _Tp*
218 begin() noexcept
219 { return data(); }
220
221 constexpr const _Tp*
222 begin() const noexcept
223 { return data(); }
224
225 constexpr _Tp*
226 end() noexcept
227 { return data() + 1; }
228
229 constexpr const _Tp*
230 end() const noexcept
231 { return data() + 1; }
232
233 static constexpr size_t
234 size() noexcept
235 { return 1; }
236
237 constexpr _Tp*
238 data() noexcept
239 { return _M_value.operator->(); }
240
241 constexpr const _Tp*
242 data() const noexcept
243 { return _M_value.operator->(); }
244
245 private:
42907ca9 246 [[no_unique_address]] __detail::__box<_Tp> _M_value;
37f33df7
JW
247 };
248
249 namespace __detail
250 {
251 template<typename _Wp>
252 constexpr auto __to_signed_like(_Wp __w) noexcept
253 {
254 if constexpr (!integral<_Wp>)
255 return iter_difference_t<_Wp>();
256 else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp))
257 return iter_difference_t<_Wp>(__w);
258 else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp))
259 return ptrdiff_t(__w);
260 else if constexpr (sizeof(long long) > sizeof(_Wp))
261 return (long long)(__w);
262#ifdef __SIZEOF_INT128__
263 else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp))
264 return __int128(__w);
265#endif
266 else
267 return __max_diff_type(__w);
268 }
269
270 template<typename _Wp>
271 using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>()));
272
273 template<typename _It>
274 concept __decrementable = incrementable<_It>
275 && requires(_It __i)
276 {
277 { --__i } -> same_as<_It&>;
278 { __i-- } -> same_as<_It>;
279 };
280
281 template<typename _It>
282 concept __advanceable = __decrementable<_It> && totally_ordered<_It>
283 && requires( _It __i, const _It __j, const __iota_diff_t<_It> __n)
284 {
285 { __i += __n } -> same_as<_It&>;
286 { __i -= __n } -> same_as<_It&>;
287 _It(__j + __n);
288 _It(__n + __j);
289 _It(__j - __n);
290 { __j - __j } -> convertible_to<__iota_diff_t<_It>>;
291 };
292
293 } // namespace __detail
294
295 template<weakly_incrementable _Winc,
296 semiregular _Bound = unreachable_sentinel_t>
297 requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound>
7f0f1083 298 && semiregular<_Winc>
37f33df7
JW
299 class iota_view : public view_interface<iota_view<_Winc, _Bound>>
300 {
301 private:
5586e506
PP
302 struct _Sentinel;
303
37f33df7
JW
304 struct _Iterator
305 {
306 private:
307 static auto
308 _S_iter_cat()
309 {
310 using namespace __detail;
311 if constexpr (__advanceable<_Winc>)
312 return random_access_iterator_tag{};
313 else if constexpr (__decrementable<_Winc>)
314 return bidirectional_iterator_tag{};
315 else if constexpr (incrementable<_Winc>)
316 return forward_iterator_tag{};
317 else
318 return input_iterator_tag{};
319 }
320
321 public:
322 using iterator_category = decltype(_S_iter_cat());
323 using value_type = _Winc;
324 using difference_type = __detail::__iota_diff_t<_Winc>;
325
326 _Iterator() = default;
327
328 constexpr explicit
329 _Iterator(_Winc __value)
330 : _M_value(__value) { }
331
332 constexpr _Winc
333 operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>)
334 { return _M_value; }
335
336 constexpr _Iterator&
337 operator++()
338 {
339 ++_M_value;
340 return *this;
341 }
342
343 constexpr void
344 operator++(int)
345 { ++*this; }
346
347 constexpr _Iterator
348 operator++(int) requires incrementable<_Winc>
349 {
350 auto __tmp = *this;
351 ++*this;
352 return __tmp;
353 }
354
355 constexpr _Iterator&
356 operator--() requires __detail::__decrementable<_Winc>
357 {
358 --_M_value;
359 return *this;
360 }
361
362 constexpr _Iterator
363 operator--(int) requires __detail::__decrementable<_Winc>
364 {
365 auto __tmp = *this;
366 --*this;
367 return __tmp;
368 }
369
370 constexpr _Iterator&
371 operator+=(difference_type __n) requires __detail::__advanceable<_Winc>
372 {
2a0f6c61
JW
373 using __detail::__is_integer_like;
374 using __detail::__is_signed_integer_like;
37f33df7
JW
375 if constexpr (__is_integer_like<_Winc>
376 && !__is_signed_integer_like<_Winc>)
377 {
378 if (__n >= difference_type(0))
379 _M_value += static_cast<_Winc>(__n);
380 else
381 _M_value -= static_cast<_Winc>(-__n);
382 }
383 else
384 _M_value += __n;
385 return *this;
386 }
387
388 constexpr _Iterator&
389 operator-=(difference_type __n) requires __detail::__advanceable<_Winc>
390 {
2a0f6c61
JW
391 using __detail::__is_integer_like;
392 using __detail::__is_signed_integer_like;
37f33df7
JW
393 if constexpr (__is_integer_like<_Winc>
394 && !__is_signed_integer_like<_Winc>)
395 {
396 if (__n >= difference_type(0))
397 _M_value -= static_cast<_Winc>(__n);
398 else
399 _M_value += static_cast<_Winc>(-__n);
400 }
401 else
402 _M_value -= __n;
403 return *this;
404 }
405
406 constexpr _Winc
407 operator[](difference_type __n) const
408 requires __detail::__advanceable<_Winc>
409 { return _Winc(_M_value + __n); }
410
411 friend constexpr bool
412 operator==(const _Iterator& __x, const _Iterator& __y)
413 requires equality_comparable<_Winc>
414 { return __x._M_value == __y._M_value; }
415
416 friend constexpr bool
417 operator<(const _Iterator& __x, const _Iterator& __y)
418 requires totally_ordered<_Winc>
419 { return __x._M_value < __y._M_value; }
420
421 friend constexpr bool
422 operator>(const _Iterator& __x, const _Iterator& __y)
423 requires totally_ordered<_Winc>
424 { return __y < __x; }
425
426 friend constexpr bool
427 operator<=(const _Iterator& __x, const _Iterator& __y)
428 requires totally_ordered<_Winc>
429 { return !(__y < __x); }
430
431 friend constexpr bool
432 operator>=(const _Iterator& __x, const _Iterator& __y)
433 requires totally_ordered<_Winc>
434 { return !(__x < __y); }
435
5713834e
JW
436#ifdef __cpp_lib_three_way_comparison
437 friend constexpr auto
37f33df7
JW
438 operator<=>(const _Iterator& __x, const _Iterator& __y)
439 requires totally_ordered<_Winc> && three_way_comparable<_Winc>
440 { return __x._M_value <=> __y._M_value; }
441#endif
442
443 friend constexpr _Iterator
444 operator+(_Iterator __i, difference_type __n)
445 requires __detail::__advanceable<_Winc>
446 { return __i += __n; }
447
448 friend constexpr _Iterator
449 operator+(difference_type __n, _Iterator __i)
450 requires __detail::__advanceable<_Winc>
451 { return __i += __n; }
452
453 friend constexpr _Iterator
454 operator-(_Iterator __i, difference_type __n)
455 requires __detail::__advanceable<_Winc>
456 { return __i -= __n; }
457
458 friend constexpr difference_type
459 operator-(const _Iterator& __x, const _Iterator& __y)
460 requires __detail::__advanceable<_Winc>
461 {
2a0f6c61
JW
462 using __detail::__is_integer_like;
463 using __detail::__is_signed_integer_like;
37f33df7
JW
464 using _Dt = difference_type;
465 if constexpr (__is_integer_like<_Winc>)
466 {
467 if constexpr (__is_signed_integer_like<_Winc>)
468 return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value));
469 else
470 return (__y._M_value > __x._M_value)
471 ? _Dt(-_Dt(__y._M_value - __x._M_value))
472 : _Dt(__x._M_value - __y._M_value);
473 }
474 else
475 return __x._M_value - __y._M_value;
476 }
477
478 private:
479 _Winc _M_value = _Winc();
5586e506
PP
480
481 friend _Sentinel;
37f33df7
JW
482 };
483
484 struct _Sentinel
485 {
486 private:
5586e506
PP
487 constexpr bool
488 _M_equal(const _Iterator& __x) const
489 { return __x._M_value == _M_bound; }
490
37f33df7
JW
491 _Bound _M_bound = _Bound();
492
493 public:
494 _Sentinel() = default;
495
496 constexpr explicit
497 _Sentinel(_Bound __bound)
498 : _M_bound(__bound) { }
499
500 friend constexpr bool
501 operator==(const _Iterator& __x, const _Sentinel& __y)
5586e506 502 { return __y._M_equal(__x); }
37f33df7
JW
503
504 friend constexpr iter_difference_t<_Winc>
505 operator-(const _Iterator& __x, const _Sentinel& __y)
506 requires sized_sentinel_for<_Bound, _Winc>
507 { return __x._M_value - __y._M_bound; }
508
509 friend constexpr iter_difference_t<_Winc>
510 operator-(const _Sentinel& __x, const _Iterator& __y)
511 requires sized_sentinel_for<_Bound, _Winc>
512 { return -(__y - __x); }
513 };
514
515 _Winc _M_value = _Winc();
62344335 516 [[no_unique_address]] _Bound _M_bound = _Bound();
37f33df7
JW
517
518 public:
519 iota_view() = default;
520
521 constexpr explicit
522 iota_view(_Winc __value)
523 : _M_value(__value)
524 { }
525
526 constexpr
527 iota_view(type_identity_t<_Winc> __value,
528 type_identity_t<_Bound> __bound)
529 : _M_value(__value), _M_bound(__bound)
530 {
531 if constexpr (totally_ordered_with<_Winc, _Bound>)
10f51543 532 __glibcxx_assert( bool(__value <= __bound) );
37f33df7
JW
533 }
534
535 constexpr _Iterator
536 begin() const { return _Iterator{_M_value}; }
537
538 constexpr auto
539 end() const
540 {
541 if constexpr (same_as<_Bound, unreachable_sentinel_t>)
542 return unreachable_sentinel;
543 else
544 return _Sentinel{_M_bound};
545 }
546
547 constexpr _Iterator
548 end() const requires same_as<_Winc, _Bound>
549 { return _Iterator{_M_bound}; }
550
551 constexpr auto
552 size() const
553 requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>)
554 || (integral<_Winc> && integral<_Bound>)
555 || sized_sentinel_for<_Bound, _Winc>
556 {
2a0f6c61
JW
557 using __detail::__is_integer_like;
558 using __detail::__to_unsigned_like;
a0e6f05d
JW
559 if constexpr (integral<_Winc> && integral<_Bound>)
560 {
561 using _Up = make_unsigned_t<decltype(_M_bound - _M_value)>;
562 return _Up(_M_bound) - _Up(_M_value);
563 }
564 else if constexpr (__is_integer_like<_Winc>)
565 return __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value);
37f33df7
JW
566 else
567 return __to_unsigned_like(_M_bound - _M_value);
568 }
569 };
570
571 template<typename _Winc, typename _Bound>
572 requires (!__detail::__is_integer_like<_Winc>
573 || !__detail::__is_integer_like<_Bound>
574 || (__detail::__is_signed_integer_like<_Winc>
575 == __detail::__is_signed_integer_like<_Bound>))
576 iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>;
577
b5b2e387 578 template<weakly_incrementable _Winc, semiregular _Bound>
15411a64
JW
579 inline constexpr bool
580 enable_borrowed_range<iota_view<_Winc, _Bound>> = true;
b5b2e387 581
37f33df7
JW
582namespace views
583{
584 template<typename _Tp>
585 inline constexpr empty_view<_Tp> empty{};
586
587 struct _Single
588 {
589 template<typename _Tp>
cba9ef06 590 constexpr auto
37f33df7
JW
591 operator()(_Tp&& __e) const
592 { return single_view{std::forward<_Tp>(__e)}; }
593 };
594
595 inline constexpr _Single single{};
596
597 struct _Iota
598 {
599 template<typename _Tp>
cba9ef06 600 constexpr auto
37f33df7
JW
601 operator()(_Tp&& __e) const
602 { return iota_view{std::forward<_Tp>(__e)}; }
603
604 template<typename _Tp, typename _Up>
cba9ef06 605 constexpr auto
37f33df7 606 operator()(_Tp&& __e, _Up&& __f) const
5586e506 607 { return iota_view{std::forward<_Tp>(__e), std::forward<_Up>(__f)}; }
37f33df7
JW
608 };
609
610 inline constexpr _Iota iota{};
cba9ef06
PP
611} // namespace views
612
b7903d9f
PP
613 namespace __detail
614 {
615 template<typename _Val, typename _CharT, typename _Traits>
616 concept __stream_extractable
617 = requires(basic_istream<_CharT, _Traits>& is, _Val& t) { is >> t; };
618 } // namespace __detail
619
620 template<movable _Val, typename _CharT, typename _Traits>
621 requires default_initializable<_Val>
622 && __detail::__stream_extractable<_Val, _CharT, _Traits>
623 class basic_istream_view
624 : public view_interface<basic_istream_view<_Val, _CharT, _Traits>>
625 {
626 public:
627 basic_istream_view() = default;
628
629 constexpr explicit
630 basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
631 : _M_stream(std::__addressof(__stream))
632 { }
633
634 constexpr auto
635 begin()
636 {
637 if (_M_stream != nullptr)
638 *_M_stream >> _M_object;
afb8da7f 639 return _Iterator{this};
b7903d9f
PP
640 }
641
642 constexpr default_sentinel_t
643 end() const noexcept
644 { return default_sentinel; }
645
646 private:
647 basic_istream<_CharT, _Traits>* _M_stream = nullptr;
648 _Val _M_object = _Val();
649
650 struct _Iterator
651 {
652 public:
76a8c0f6 653 using iterator_concept = input_iterator_tag;
b7903d9f
PP
654 using difference_type = ptrdiff_t;
655 using value_type = _Val;
656
657 _Iterator() = default;
658
659 constexpr explicit
afb8da7f
PP
660 _Iterator(basic_istream_view* __parent) noexcept
661 : _M_parent(__parent)
b7903d9f
PP
662 { }
663
664 _Iterator(const _Iterator&) = delete;
665 _Iterator(_Iterator&&) = default;
666 _Iterator& operator=(const _Iterator&) = delete;
667 _Iterator& operator=(_Iterator&&) = default;
668
669 _Iterator&
670 operator++()
671 {
672 __glibcxx_assert(_M_parent->_M_stream != nullptr);
673 *_M_parent->_M_stream >> _M_parent->_M_object;
572992c8 674 return *this;
b7903d9f
PP
675 }
676
677 void
678 operator++(int)
679 { ++*this; }
680
681 _Val&
682 operator*() const
683 {
684 __glibcxx_assert(_M_parent->_M_stream != nullptr);
685 return _M_parent->_M_object;
686 }
687
688 friend bool
689 operator==(const _Iterator& __x, default_sentinel_t)
690 { return __x._M_at_end(); }
691
692 private:
693 basic_istream_view* _M_parent = nullptr;
694
695 bool
696 _M_at_end() const
697 { return _M_parent == nullptr || !*_M_parent->_M_stream; }
698 };
699
700 friend _Iterator;
701 };
702
703 template<typename _Val, typename _CharT, typename _Traits>
704 basic_istream_view<_Val, _CharT, _Traits>
705 istream_view(basic_istream<_CharT, _Traits>& __s)
706 { return basic_istream_view<_Val, _CharT, _Traits>{__s}; }
707
160061ac
JW
708 // C++20 24.7 [range.adaptors] Range adaptors
709
cba9ef06
PP
710namespace __detail
711{
712 struct _Empty { };
8017d95c 713
4c391563
JW
714 // Alias for a type that is conditionally present
715 // (and is an empty type otherwise).
716 // Data members using this alias should use [[no_unique_address]] so that
717 // they take no space when not needed.
718 template<bool _Present, typename _Tp>
719 using __maybe_present_t = conditional_t<_Present, _Tp, _Empty>;
720
721 // Alias for a type that is conditionally const.
8017d95c
JW
722 template<bool _Const, typename _Tp>
723 using __maybe_const_t = conditional_t<_Const, const _Tp, _Tp>;
724
cba9ef06
PP
725} // namespace __detail
726
727namespace views
728{
729 namespace __adaptor
730 {
6e63438a
PP
731 template<typename _Tp>
732 inline constexpr auto
733 __maybe_refwrap(_Tp& __arg)
734 { return reference_wrapper<_Tp>{__arg}; }
735
736 template<typename _Tp>
737 inline constexpr auto
738 __maybe_refwrap(const _Tp& __arg)
739 { return reference_wrapper<const _Tp>{__arg}; }
740
741 template<typename _Tp>
742 inline constexpr decltype(auto)
743 __maybe_refwrap(_Tp&& __arg)
744 { return std::forward<_Tp>(__arg); }
745
cba9ef06
PP
746 template<typename _Callable>
747 struct _RangeAdaptorClosure;
748
749 template<typename _Callable>
750 struct _RangeAdaptor
751 {
752 protected:
753 [[no_unique_address]]
4c391563
JW
754 __detail::__maybe_present_t<!is_default_constructible_v<_Callable>,
755 _Callable> _M_callable;
cba9ef06
PP
756
757 public:
758 constexpr
759 _RangeAdaptor(const _Callable& = {})
760 requires is_default_constructible_v<_Callable>
761 { }
762
763 constexpr
764 _RangeAdaptor(_Callable __callable)
765 requires (!is_default_constructible_v<_Callable>)
766 : _M_callable(std::move(__callable))
767 { }
768
769 template<typename... _Args>
770 requires (sizeof...(_Args) >= 1)
771 constexpr auto
772 operator()(_Args&&... __args) const
773 {
6e63438a
PP
774 // [range.adaptor.object]: If a range adaptor object accepts more
775 // than one argument, then the following expressions are equivalent:
776 //
777 // (1) adaptor(range, args...)
778 // (2) adaptor(args...)(range)
779 // (3) range | adaptor(args...)
780 //
781 // In this case, adaptor(args...) is a range adaptor closure object.
782 //
783 // We handle (1) and (2) here, and (3) is just a special case of a
784 // more general case already handled by _RangeAdaptorClosure.
cba9ef06
PP
785 if constexpr (is_invocable_v<_Callable, _Args...>)
786 {
787 static_assert(sizeof...(_Args) != 1,
788 "a _RangeAdaptor that accepts only one argument "
789 "should be defined as a _RangeAdaptorClosure");
6e63438a
PP
790 // Here we handle adaptor(range, args...) -- just forward all
791 // arguments to the underlying adaptor routine.
cba9ef06
PP
792 return _Callable{}(std::forward<_Args>(__args)...);
793 }
794 else
795 {
6e63438a
PP
796 // Here we handle adaptor(args...)(range).
797 // Given args..., we return a _RangeAdaptorClosure that takes a
798 // range argument, such that (2) is equivalent to (1).
799 //
800 // We need to be careful about how we capture args... in this
801 // closure. By using __maybe_refwrap, we capture lvalue
802 // references by reference (through a reference_wrapper) and
803 // otherwise capture by value.
804 auto __closure
805 = [...__args(__maybe_refwrap(std::forward<_Args>(__args)))]
806 <typename _Range> (_Range&& __r) {
807 // This static_cast has two purposes: it forwards a
808 // reference_wrapper<T> capture as a T&, and otherwise
809 // forwards the captured argument as an rvalue.
810 return _Callable{}(std::forward<_Range>(__r),
811 (static_cast<unwrap_reference_t
812 <remove_const_t<decltype(__args)>>>
813 (__args))...);
814 };
cba9ef06
PP
815 using _ClosureType = decltype(__closure);
816 return _RangeAdaptorClosure<_ClosureType>(std::move(__closure));
817 }
818 }
819 };
820
a5b213dd
JW
821 template<typename _Callable>
822 _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>;
823
cba9ef06
PP
824 template<typename _Callable>
825 struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable>
826 {
827 using _RangeAdaptor<_Callable>::_RangeAdaptor;
828
829 template<viewable_range _Range>
830 requires requires { declval<_Callable>()(declval<_Range>()); }
831 constexpr auto
832 operator()(_Range&& __r) const
833 {
834 if constexpr (is_default_constructible_v<_Callable>)
835 return _Callable{}(std::forward<_Range>(__r));
836 else
837 return this->_M_callable(std::forward<_Range>(__r));
838 }
839
840 template<viewable_range _Range>
841 requires requires { declval<_Callable>()(declval<_Range>()); }
842 friend constexpr auto
843 operator|(_Range&& __r, const _RangeAdaptorClosure& __o)
844 { return __o(std::forward<_Range>(__r)); }
37f33df7 845
cba9ef06
PP
846 template<typename _Tp>
847 friend constexpr auto
848 operator|(const _RangeAdaptorClosure<_Tp>& __x,
849 const _RangeAdaptorClosure& __y)
850 {
851 if constexpr (is_default_constructible_v<_Tp>
852 && is_default_constructible_v<_Callable>)
853 {
854 auto __closure = [] <typename _Up> (_Up&& __e) {
855 return std::forward<_Up>(__e) | decltype(__x){} | decltype(__y){};
856 };
857 return _RangeAdaptorClosure<decltype(__closure)>(__closure);
858 }
859 else if constexpr (is_default_constructible_v<_Tp>
860 && !is_default_constructible_v<_Callable>)
861 {
862 auto __closure = [__y] <typename _Up> (_Up&& __e) {
863 return std::forward<_Up>(__e) | decltype(__x){} | __y;
864 };
865 return _RangeAdaptorClosure<decltype(__closure)>(__closure);
866 }
867 else if constexpr (!is_default_constructible_v<_Tp>
868 && is_default_constructible_v<_Callable>)
869 {
870 auto __closure = [__x] <typename _Up> (_Up&& __e) {
871 return std::forward<_Up>(__e) | __x | decltype(__y){};
872 };
873 return _RangeAdaptorClosure<decltype(__closure)>(__closure);
874 }
875 else
876 {
877 auto __closure = [__x, __y] <typename _Up> (_Up&& __e) {
878 return std::forward<_Up>(__e) | __x | __y;
879 };
880 return _RangeAdaptorClosure<decltype(__closure)>(__closure);
881 }
882 }
883 };
884
885 template<typename _Callable>
886 _RangeAdaptorClosure(_Callable) -> _RangeAdaptorClosure<_Callable>;
887 } // namespace __adaptor
37f33df7 888} // namespace views
cba9ef06
PP
889
890 template<range _Range> requires is_object_v<_Range>
891 class ref_view : public view_interface<ref_view<_Range>>
892 {
893 private:
894 _Range* _M_r = nullptr;
895
896 static void _S_fun(_Range&); // not defined
897 static void _S_fun(_Range&&) = delete;
898
899 public:
900 constexpr
901 ref_view() noexcept = default;
902
903 template<__detail::__not_same_as<ref_view> _Tp>
904 requires convertible_to<_Tp, _Range&>
905 && requires { _S_fun(declval<_Tp>()); }
906 constexpr
907 ref_view(_Tp&& __t)
908 : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t))))
909 { }
910
911 constexpr _Range&
912 base() const
913 { return *_M_r; }
914
915 constexpr iterator_t<_Range>
916 begin() const
917 { return ranges::begin(*_M_r); }
918
919 constexpr sentinel_t<_Range>
920 end() const
921 { return ranges::end(*_M_r); }
922
923 constexpr bool
924 empty() const requires requires { ranges::empty(*_M_r); }
925 { return ranges::empty(*_M_r); }
926
927 constexpr auto
928 size() const requires sized_range<_Range>
929 { return ranges::size(*_M_r); }
930
931 constexpr auto
932 data() const requires contiguous_range<_Range>
933 { return ranges::data(*_M_r); }
934 };
935
936 template<typename _Range>
937 ref_view(_Range&) -> ref_view<_Range>;
938
939 template<typename _Tp>
15411a64 940 inline constexpr bool enable_borrowed_range<ref_view<_Tp>> = true;
cba9ef06
PP
941
942 namespace views
943 {
944 inline constexpr __adaptor::_RangeAdaptorClosure all
945 = [] <viewable_range _Range> (_Range&& __r)
946 {
947 if constexpr (view<decay_t<_Range>>)
948 return std::forward<_Range>(__r);
949 else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; })
950 return ref_view{std::forward<_Range>(__r)};
951 else
952 return subrange{std::forward<_Range>(__r)};
953 };
cba9ef06 954
aca60ecf
JW
955 template<viewable_range _Range>
956 using all_t = decltype(all(std::declval<_Range>()));
957
958 } // namespace views
cba9ef06
PP
959
960 // XXX: the following algos are copied from ranges_algo.h to avoid a circular
961 // dependency with that header.
962 namespace __detail
963 {
964 template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
965 typename _Proj = identity,
966 indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
967 constexpr _Iter
968 find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
969 {
970 while (__first != __last
971 && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
972 ++__first;
973 return __first;
974 }
975
976 template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
977 typename _Proj = identity,
978 indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
979 constexpr _Iter
980 find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {})
981 {
982 while (__first != __last
983 && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first)))
984 ++__first;
985 return __first;
986 }
987
988 template<typename _Tp, typename _Proj = identity,
989 indirect_strict_weak_order<projected<const _Tp*, _Proj>>
990 _Comp = ranges::less>
991 constexpr const _Tp&
992 min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {})
993 {
994 if (std::__invoke(std::move(__comp),
995 std::__invoke(__proj, __b),
996 std::__invoke(__proj, __a)))
997 return __b;
998 else
999 return __a;
1000 }
1001
1002 template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
1003 input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
1004 typename _Pred = ranges::equal_to,
1005 typename _Proj1 = identity, typename _Proj2 = identity>
1006 requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
1007 constexpr pair<_Iter1, _Iter2>
1008 mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
1009 _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
1010 {
1011 while (__first1 != __last1 && __first2 != __last2
1012 && (bool)std::__invoke(__pred,
1013 std::__invoke(__proj1, *__first1),
1014 std::__invoke(__proj2, *__first2)))
1015 {
1016 ++__first1;
1017 ++__first2;
1018 }
1019 return { std::move(__first1), std::move(__first2) };
1020 }
1021 } // namespace __detail
1022
a1535015
PP
1023 namespace __detail
1024 {
1025 template<range _Range>
1026 struct _CachedPosition
1027 {
1028 constexpr bool
1029 _M_has_value() const
1030 { return false; }
1031
1032 constexpr iterator_t<_Range>
1033 _M_get(const _Range&) const
1034 {
1035 __glibcxx_assert(false);
1036 return {};
1037 }
1038
1039 constexpr void
1040 _M_set(const _Range&, const iterator_t<_Range>&) const
1041 { }
1042 };
1043
1044 template<forward_range _Range>
1045 struct _CachedPosition<_Range>
1046 {
1047 private:
1048 iterator_t<_Range> _M_iter{};
1049
1050 public:
1051 constexpr bool
1052 _M_has_value() const
1053 { return _M_iter != iterator_t<_Range>{}; }
1054
1055 constexpr iterator_t<_Range>
1056 _M_get(const _Range&) const
1057 {
1058 __glibcxx_assert(_M_has_value());
1059 return _M_iter;
1060 }
1061
1062 constexpr void
1063 _M_set(const _Range&, const iterator_t<_Range>& __it)
1064 {
1065 __glibcxx_assert(!_M_has_value());
1066 _M_iter = __it;
1067 }
1068 };
1069
1070 template<random_access_range _Range>
1071 requires (sizeof(range_difference_t<_Range>)
1072 <= sizeof(iterator_t<_Range>))
1073 struct _CachedPosition<_Range>
1074 {
1075 private:
1076 range_difference_t<_Range> _M_offset = -1;
1077
1078 public:
1079 constexpr bool
1080 _M_has_value() const
1081 { return _M_offset >= 0; }
1082
1083 constexpr iterator_t<_Range>
1084 _M_get(_Range& __r) const
1085 {
1086 __glibcxx_assert(_M_has_value());
1087 return ranges::begin(__r) + _M_offset;
1088 }
1089
1090 constexpr void
1091 _M_set(_Range& __r, const iterator_t<_Range>& __it)
1092 {
1093 __glibcxx_assert(!_M_has_value());
1094 _M_offset = __it - ranges::begin(__r);
1095 }
1096 };
1097
1098 } // namespace __detail
1099
cba9ef06
PP
1100 template<input_range _Vp,
1101 indirect_unary_predicate<iterator_t<_Vp>> _Pred>
1102 requires view<_Vp> && is_object_v<_Pred>
1103 class filter_view : public view_interface<filter_view<_Vp, _Pred>>
1104 {
1105 private:
1106 struct _Sentinel;
1107
1108 struct _Iterator
1109 {
1110 private:
1111 static constexpr auto
1112 _S_iter_concept()
1113 {
1114 if constexpr (bidirectional_range<_Vp>)
1115 return bidirectional_iterator_tag{};
1116 else if constexpr (forward_range<_Vp>)
1117 return forward_iterator_tag{};
1118 else
1119 return input_iterator_tag{};
1120 }
1121
1122 static constexpr auto
1123 _S_iter_cat()
1124 {
a5b213dd 1125 using _Cat = typename iterator_traits<_Vp_iter>::iterator_category;
cba9ef06
PP
1126 if constexpr (derived_from<_Cat, bidirectional_iterator_tag>)
1127 return bidirectional_iterator_tag{};
1128 else if constexpr (derived_from<_Cat, forward_iterator_tag>)
1129 return forward_iterator_tag{};
1130 else
1131 return _Cat{};
1132 }
1133
1134 friend filter_view;
1135
a5b213dd
JW
1136 using _Vp_iter = iterator_t<_Vp>;
1137
1138 _Vp_iter _M_current = _Vp_iter();
cba9ef06
PP
1139 filter_view* _M_parent = nullptr;
1140
1141 public:
1142 using iterator_concept = decltype(_S_iter_concept());
1143 using iterator_category = decltype(_S_iter_cat());
1144 using value_type = range_value_t<_Vp>;
1145 using difference_type = range_difference_t<_Vp>;
1146
1147 _Iterator() = default;
1148
1149 constexpr
afb8da7f 1150 _Iterator(filter_view* __parent, _Vp_iter __current)
cba9ef06 1151 : _M_current(std::move(__current)),
afb8da7f 1152 _M_parent(__parent)
cba9ef06
PP
1153 { }
1154
a5b213dd 1155 constexpr _Vp_iter
cba9ef06 1156 base() const &
a5b213dd 1157 requires copyable<_Vp_iter>
cba9ef06
PP
1158 { return _M_current; }
1159
a5b213dd 1160 constexpr _Vp_iter
cba9ef06
PP
1161 base() &&
1162 { return std::move(_M_current); }
1163
1164 constexpr range_reference_t<_Vp>
1165 operator*() const
1166 { return *_M_current; }
1167
a5b213dd 1168 constexpr _Vp_iter
cba9ef06 1169 operator->() const
a5b213dd
JW
1170 requires __detail::__has_arrow<_Vp_iter>
1171 && copyable<_Vp_iter>
cba9ef06
PP
1172 { return _M_current; }
1173
1174 constexpr _Iterator&
1175 operator++()
1176 {
1177 _M_current = __detail::find_if(std::move(++_M_current),
1178 ranges::end(_M_parent->_M_base),
1179 std::ref(*_M_parent->_M_pred));
1180 return *this;
1181 }
1182
1183 constexpr void
1184 operator++(int)
1185 { ++*this; }
1186
1187 constexpr _Iterator
1188 operator++(int) requires forward_range<_Vp>
1189 {
1190 auto __tmp = *this;
1191 ++*this;
1192 return __tmp;
1193 }
1194
1195 constexpr _Iterator&
1196 operator--() requires bidirectional_range<_Vp>
1197 {
1198 do
1199 --_M_current;
1200 while (!std::__invoke(*_M_parent->_M_pred, *_M_current));
1201 return *this;
1202 }
1203
1204 constexpr _Iterator
1205 operator--(int) requires bidirectional_range<_Vp>
1206 {
1207 auto __tmp = *this;
1208 --*this;
1209 return __tmp;
1210 }
1211
1212 friend constexpr bool
1213 operator==(const _Iterator& __x, const _Iterator& __y)
a5b213dd 1214 requires equality_comparable<_Vp_iter>
cba9ef06
PP
1215 { return __x._M_current == __y._M_current; }
1216
1217 friend constexpr range_rvalue_reference_t<_Vp>
1218 iter_move(const _Iterator& __i)
1219 noexcept(noexcept(ranges::iter_move(__i._M_current)))
1220 { return ranges::iter_move(__i._M_current); }
1221
1222 friend constexpr void
1223 iter_swap(const _Iterator& __x, const _Iterator& __y)
1224 noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
a5b213dd 1225 requires indirectly_swappable<_Vp_iter>
cba9ef06
PP
1226 { ranges::iter_swap(__x._M_current, __y._M_current); }
1227 };
1228
1229 struct _Sentinel
1230 {
1231 private:
1232 sentinel_t<_Vp> _M_end = sentinel_t<_Vp>();
1233
1234 constexpr bool
1235 __equal(const _Iterator& __i) const
1236 { return __i._M_current == _M_end; }
1237
1238 public:
1239 _Sentinel() = default;
1240
1241 constexpr explicit
afb8da7f
PP
1242 _Sentinel(filter_view* __parent)
1243 : _M_end(ranges::end(__parent->_M_base))
cba9ef06
PP
1244 { }
1245
1246 constexpr sentinel_t<_Vp>
1247 base() const
1248 { return _M_end; }
1249
1250 friend constexpr bool
1251 operator==(const _Iterator& __x, const _Sentinel& __y)
1252 { return __y.__equal(__x); }
1253 };
1254
42907ca9 1255 [[no_unique_address]] __detail::__box<_Pred> _M_pred;
a1535015 1256 [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
361e32ee 1257 _Vp _M_base = _Vp();
cba9ef06
PP
1258
1259 public:
1260 filter_view() = default;
1261
1262 constexpr
1263 filter_view(_Vp __base, _Pred __pred)
361e32ee 1264 : _M_pred(std::move(__pred)), _M_base(std::move(__base))
cba9ef06
PP
1265 { }
1266
cba9ef06
PP
1267 constexpr _Vp
1268 base() const& requires copy_constructible<_Vp>
1269 { return _M_base; }
1270
1271 constexpr _Vp
1272 base() &&
1273 { return std::move(_M_base); }
1274
242b4fb7
PP
1275 constexpr const _Pred&
1276 pred() const
1277 { return *_M_pred; }
1278
cba9ef06
PP
1279 constexpr _Iterator
1280 begin()
1281 {
a1535015 1282 if (_M_cached_begin._M_has_value())
afb8da7f 1283 return {this, _M_cached_begin._M_get(_M_base)};
a1535015 1284
cba9ef06 1285 __glibcxx_assert(_M_pred.has_value());
a1535015
PP
1286 auto __it = __detail::find_if(ranges::begin(_M_base),
1287 ranges::end(_M_base),
1288 std::ref(*_M_pred));
1289 _M_cached_begin._M_set(_M_base, __it);
afb8da7f 1290 return {this, std::move(__it)};
cba9ef06
PP
1291 }
1292
1293 constexpr auto
1294 end()
1295 {
1296 if constexpr (common_range<_Vp>)
afb8da7f 1297 return _Iterator{this, ranges::end(_M_base)};
cba9ef06 1298 else
afb8da7f 1299 return _Sentinel{this};
cba9ef06
PP
1300 }
1301 };
1302
1303 template<typename _Range, typename _Pred>
aca60ecf 1304 filter_view(_Range&&, _Pred) -> filter_view<views::all_t<_Range>, _Pred>;
cba9ef06
PP
1305
1306 namespace views
1307 {
1308 inline constexpr __adaptor::_RangeAdaptor filter
1309 = [] <viewable_range _Range, typename _Pred> (_Range&& __r, _Pred&& __p)
1310 {
1311 return filter_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)};
1312 };
1313 } // namespace views
1314
1315 template<input_range _Vp, copy_constructible _Fp>
1316 requires view<_Vp> && is_object_v<_Fp>
1317 && regular_invocable<_Fp&, range_reference_t<_Vp>>
ec15da7c
PP
1318 && std::__detail::__can_reference<invoke_result_t<_Fp&,
1319 range_reference_t<_Vp>>>
cba9ef06
PP
1320 class transform_view : public view_interface<transform_view<_Vp, _Fp>>
1321 {
1322 private:
1323 template<bool _Const>
1324 struct _Sentinel;
1325
1326 template<bool _Const>
1327 struct _Iterator
1328 {
1329 private:
8017d95c
JW
1330 using _Parent = __detail::__maybe_const_t<_Const, transform_view>;
1331 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06
PP
1332
1333 static constexpr auto
1334 _S_iter_concept()
1335 {
1336 if constexpr (random_access_range<_Vp>)
1337 return random_access_iterator_tag{};
1338 else if constexpr (bidirectional_range<_Vp>)
1339 return bidirectional_iterator_tag{};
1340 else if constexpr (forward_range<_Vp>)
1341 return forward_iterator_tag{};
1342 else
1343 return input_iterator_tag{};
1344 }
1345
1346 static constexpr auto
1347 _S_iter_cat()
1348 {
510bd1c1
PP
1349 using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>;
1350 if constexpr (is_lvalue_reference_v<_Res>)
1351 {
1352 using _Cat
1353 = typename iterator_traits<_Base_iter>::iterator_category;
1354 if constexpr (derived_from<_Cat, contiguous_iterator_tag>)
1355 return random_access_iterator_tag{};
1356 else
1357 return _Cat{};
1358 }
cba9ef06 1359 else
510bd1c1 1360 return input_iterator_tag{};
cba9ef06
PP
1361 }
1362
a5b213dd
JW
1363 using _Base_iter = iterator_t<_Base>;
1364
1365 _Base_iter _M_current = _Base_iter();
cba9ef06
PP
1366 _Parent* _M_parent = nullptr;
1367
1368 public:
1369 using iterator_concept = decltype(_S_iter_concept());
1370 using iterator_category = decltype(_S_iter_cat());
1371 using value_type
1372 = remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>;
1373 using difference_type = range_difference_t<_Base>;
1374
1375 _Iterator() = default;
1376
1377 constexpr
afb8da7f 1378 _Iterator(_Parent* __parent, _Base_iter __current)
cba9ef06 1379 : _M_current(std::move(__current)),
afb8da7f 1380 _M_parent(__parent)
cba9ef06
PP
1381 { }
1382
1383 constexpr
1384 _Iterator(_Iterator<!_Const> __i)
1385 requires _Const
a5b213dd 1386 && convertible_to<iterator_t<_Vp>, _Base_iter>
cba9ef06
PP
1387 : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent)
1388 { }
1389
a5b213dd 1390 constexpr _Base_iter
cba9ef06 1391 base() const &
a5b213dd 1392 requires copyable<_Base_iter>
cba9ef06
PP
1393 { return _M_current; }
1394
a5b213dd 1395 constexpr _Base_iter
cba9ef06
PP
1396 base() &&
1397 { return std::move(_M_current); }
1398
1399 constexpr decltype(auto)
1400 operator*() const
cf0c3a45 1401 noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current)))
cba9ef06
PP
1402 { return std::__invoke(*_M_parent->_M_fun, *_M_current); }
1403
1404 constexpr _Iterator&
1405 operator++()
1406 {
1407 ++_M_current;
1408 return *this;
1409 }
1410
1411 constexpr void
1412 operator++(int)
1413 { ++_M_current; }
1414
1415 constexpr _Iterator
1416 operator++(int) requires forward_range<_Base>
1417 {
1418 auto __tmp = *this;
1419 ++*this;
1420 return __tmp;
1421 }
1422
1423 constexpr _Iterator&
1424 operator--() requires bidirectional_range<_Base>
1425 {
1426 --_M_current;
1427 return *this;
1428 }
1429
1430 constexpr _Iterator
1431 operator--(int) requires bidirectional_range<_Base>
1432 {
1433 auto __tmp = *this;
1434 --*this;
1435 return __tmp;
1436 }
1437
1438 constexpr _Iterator&
1439 operator+=(difference_type __n) requires random_access_range<_Base>
1440 {
1441 _M_current += __n;
1442 return *this;
1443 }
1444
1445 constexpr _Iterator&
1446 operator-=(difference_type __n) requires random_access_range<_Base>
1447 {
1448 _M_current -= __n;
1449 return *this;
1450 }
1451
1452 constexpr decltype(auto)
1453 operator[](difference_type __n) const
1454 requires random_access_range<_Base>
1455 { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); }
1456
1457 friend constexpr bool
1458 operator==(const _Iterator& __x, const _Iterator& __y)
a5b213dd 1459 requires equality_comparable<_Base_iter>
cba9ef06
PP
1460 { return __x._M_current == __y._M_current; }
1461
1462 friend constexpr bool
1463 operator<(const _Iterator& __x, const _Iterator& __y)
1464 requires random_access_range<_Base>
1465 { return __x._M_current < __y._M_current; }
1466
1467 friend constexpr bool
1468 operator>(const _Iterator& __x, const _Iterator& __y)
1469 requires random_access_range<_Base>
1470 { return __y < __x; }
1471
1472 friend constexpr bool
1473 operator<=(const _Iterator& __x, const _Iterator& __y)
1474 requires random_access_range<_Base>
1475 { return !(__y < __x); }
1476
1477 friend constexpr bool
1478 operator>=(const _Iterator& __x, const _Iterator& __y)
1479 requires random_access_range<_Base>
1480 { return !(__x < __y); }
1481
1482#ifdef __cpp_lib_three_way_comparison
1483 friend constexpr auto
1484 operator<=>(const _Iterator& __x, const _Iterator& __y)
1485 requires random_access_range<_Base>
a5b213dd 1486 && three_way_comparable<_Base_iter>
cba9ef06
PP
1487 { return __x._M_current <=> __y._M_current; }
1488#endif
1489
1490 friend constexpr _Iterator
1491 operator+(_Iterator __i, difference_type __n)
1492 requires random_access_range<_Base>
afb8da7f 1493 { return {__i._M_parent, __i._M_current + __n}; }
cba9ef06
PP
1494
1495 friend constexpr _Iterator
1496 operator+(difference_type __n, _Iterator __i)
1497 requires random_access_range<_Base>
afb8da7f 1498 { return {__i._M_parent, __i._M_current + __n}; }
cba9ef06
PP
1499
1500 friend constexpr _Iterator
1501 operator-(_Iterator __i, difference_type __n)
1502 requires random_access_range<_Base>
afb8da7f 1503 { return {__i._M_parent, __i._M_current - __n}; }
cba9ef06 1504
2ec58cfc
JW
1505 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1506 // 3483. transform_view::iterator's difference is overconstrained
cba9ef06
PP
1507 friend constexpr difference_type
1508 operator-(const _Iterator& __x, const _Iterator& __y)
2ec58cfc 1509 requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
cba9ef06
PP
1510 { return __x._M_current - __y._M_current; }
1511
1512 friend constexpr decltype(auto)
cf0c3a45
JW
1513 iter_move(const _Iterator& __i) noexcept(noexcept(*__i))
1514 {
1515 if constexpr (is_lvalue_reference_v<decltype(*__i)>)
1516 return std::move(*__i);
1517 else
1518 return *__i;
1519 }
cba9ef06
PP
1520
1521 friend constexpr void
1522 iter_swap(const _Iterator& __x, const _Iterator& __y)
1523 noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
a5b213dd 1524 requires indirectly_swappable<_Base_iter>
cba9ef06
PP
1525 { return ranges::iter_swap(__x._M_current, __y._M_current); }
1526
ba49e9eb 1527 friend _Iterator<!_Const>;
6c2582c0 1528 template<bool> friend struct _Sentinel;
cba9ef06
PP
1529 };
1530
1531 template<bool _Const>
1532 struct _Sentinel
1533 {
1534 private:
8017d95c
JW
1535 using _Parent = __detail::__maybe_const_t<_Const, transform_view>;
1536 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06 1537
6c2582c0 1538 template<bool _Const2>
3ae0cd94 1539 constexpr auto
6c2582c0
JW
1540 __distance_from(const _Iterator<_Const2>& __i) const
1541 { return _M_end - __i._M_current; }
cba9ef06 1542
6c2582c0
JW
1543 template<bool _Const2>
1544 constexpr bool
1545 __equal(const _Iterator<_Const2>& __i) const
1546 { return __i._M_current == _M_end; }
cba9ef06
PP
1547
1548 sentinel_t<_Base> _M_end = sentinel_t<_Base>();
1549
1550 public:
1551 _Sentinel() = default;
1552
1553 constexpr explicit
1554 _Sentinel(sentinel_t<_Base> __end)
1555 : _M_end(__end)
1556 { }
1557
1558 constexpr
1559 _Sentinel(_Sentinel<!_Const> __i)
1560 requires _Const
1561 && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>
1562 : _M_end(std::move(__i._M_end))
1563 { }
1564
1565 constexpr sentinel_t<_Base>
1566 base() const
1567 { return _M_end; }
1568
6c2582c0
JW
1569 template<bool _Const2>
1570 requires sentinel_for<sentinel_t<_Base>,
1571 iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>>
1572 friend constexpr bool
1573 operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)
1574 { return __y.__equal(__x); }
1575
3ae0cd94
PP
1576 template<bool _Const2,
1577 typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
1578 requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
1579 friend constexpr range_difference_t<_Base2>
6c2582c0
JW
1580 operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y)
1581 { return -__y.__distance_from(__x); }
1582
3ae0cd94
PP
1583 template<bool _Const2,
1584 typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
1585 requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
1586 friend constexpr range_difference_t<_Base2>
6c2582c0
JW
1587 operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x)
1588 { return __y.__distance_from(__x); }
ba49e9eb
PP
1589
1590 friend _Sentinel<!_Const>;
cba9ef06
PP
1591 };
1592
42907ca9 1593 [[no_unique_address]] __detail::__box<_Fp> _M_fun;
361e32ee 1594 _Vp _M_base = _Vp();
cba9ef06
PP
1595
1596 public:
1597 transform_view() = default;
1598
1599 constexpr
1600 transform_view(_Vp __base, _Fp __fun)
361e32ee 1601 : _M_fun(std::move(__fun)), _M_base(std::move(__base))
cba9ef06
PP
1602 { }
1603
cba9ef06
PP
1604 constexpr _Vp
1605 base() const& requires copy_constructible<_Vp>
1606 { return _M_base ; }
1607
1608 constexpr _Vp
1609 base() &&
1610 { return std::move(_M_base); }
1611
1612 constexpr _Iterator<false>
1613 begin()
afb8da7f 1614 { return _Iterator<false>{this, ranges::begin(_M_base)}; }
cba9ef06
PP
1615
1616 constexpr _Iterator<true>
1617 begin() const
1618 requires range<const _Vp>
1619 && regular_invocable<const _Fp&, range_reference_t<const _Vp>>
afb8da7f 1620 { return _Iterator<true>{this, ranges::begin(_M_base)}; }
cba9ef06
PP
1621
1622 constexpr _Sentinel<false>
1623 end()
1624 { return _Sentinel<false>{ranges::end(_M_base)}; }
1625
1626 constexpr _Iterator<false>
1627 end() requires common_range<_Vp>
afb8da7f 1628 { return _Iterator<false>{this, ranges::end(_M_base)}; }
cba9ef06
PP
1629
1630 constexpr _Sentinel<true>
1631 end() const
1632 requires range<const _Vp>
1633 && regular_invocable<const _Fp&, range_reference_t<const _Vp>>
1634 { return _Sentinel<true>{ranges::end(_M_base)}; }
1635
1636 constexpr _Iterator<true>
1637 end() const
1638 requires common_range<const _Vp>
1639 && regular_invocable<const _Fp&, range_reference_t<const _Vp>>
afb8da7f 1640 { return _Iterator<true>{this, ranges::end(_M_base)}; }
cba9ef06
PP
1641
1642 constexpr auto
1643 size() requires sized_range<_Vp>
1644 { return ranges::size(_M_base); }
1645
1646 constexpr auto
1647 size() const requires sized_range<const _Vp>
1648 { return ranges::size(_M_base); }
1649 };
1650
1651 template<typename _Range, typename _Fp>
aca60ecf 1652 transform_view(_Range&&, _Fp) -> transform_view<views::all_t<_Range>, _Fp>;
cba9ef06
PP
1653
1654 namespace views
1655 {
1656 inline constexpr __adaptor::_RangeAdaptor transform
1657 = [] <viewable_range _Range, typename _Fp> (_Range&& __r, _Fp&& __f)
1658 {
1659 return transform_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)};
1660 };
1661 } // namespace views
1662
1663 template<view _Vp>
1664 class take_view : public view_interface<take_view<_Vp>>
1665 {
1666 private:
e066821b
PP
1667 template<bool _Const>
1668 using _CI = counted_iterator<
1669 iterator_t<__detail::__maybe_const_t<_Const, _Vp>>>;
1670
cba9ef06
PP
1671 template<bool _Const>
1672 struct _Sentinel
1673 {
1674 private:
8017d95c 1675 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06
PP
1676 sentinel_t<_Base> _M_end = sentinel_t<_Base>();
1677
1678 public:
1679 _Sentinel() = default;
1680
1681 constexpr explicit
1682 _Sentinel(sentinel_t<_Base> __end)
1683 : _M_end(__end)
1684 { }
1685
1686 constexpr
1687 _Sentinel(_Sentinel<!_Const> __s)
1688 requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>
1689 : _M_end(std::move(__s._M_end))
1690 { }
1691
1692 constexpr sentinel_t<_Base>
1693 base() const
1694 { return _M_end; }
1695
e066821b
PP
1696 friend constexpr bool
1697 operator==(const _CI<_Const>& __y, const _Sentinel& __x)
1698 { return __y.count() == 0 || __y.base() == __x._M_end; }
1699
1700 template<bool _OtherConst = !_Const,
1701 typename _Base2 = __detail::__maybe_const_t<_OtherConst, _Vp>>
1702 requires sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
1703 friend constexpr bool
1704 operator==(const _CI<_OtherConst>& __y, const _Sentinel& __x)
cba9ef06 1705 { return __y.count() == 0 || __y.base() == __x._M_end; }
ba49e9eb
PP
1706
1707 friend _Sentinel<!_Const>;
cba9ef06
PP
1708 };
1709
cba9ef06 1710 range_difference_t<_Vp> _M_count = 0;
361e32ee 1711 _Vp _M_base = _Vp();
cba9ef06
PP
1712
1713 public:
1714 take_view() = default;
1715
1716 constexpr
1717 take_view(_Vp base, range_difference_t<_Vp> __count)
361e32ee 1718 : _M_count(std::move(__count)), _M_base(std::move(base))
cba9ef06
PP
1719 { }
1720
cba9ef06
PP
1721 constexpr _Vp
1722 base() const& requires copy_constructible<_Vp>
1723 { return _M_base; }
1724
1725 constexpr _Vp
1726 base() &&
1727 { return std::move(_M_base); }
1728
1729 constexpr auto
1730 begin() requires (!__detail::__simple_view<_Vp>)
1731 {
1732 if constexpr (sized_range<_Vp>)
1733 {
1734 if constexpr (random_access_range<_Vp>)
1735 return ranges::begin(_M_base);
1736 else
8f0d8cd8
PP
1737 {
1738 auto __sz = size();
1739 return counted_iterator{ranges::begin(_M_base), __sz};
1740 }
cba9ef06
PP
1741 }
1742 else
1743 return counted_iterator{ranges::begin(_M_base), _M_count};
1744 }
1745
1746 constexpr auto
1747 begin() const requires range<const _Vp>
1748 {
1749 if constexpr (sized_range<const _Vp>)
1750 {
1751 if constexpr (random_access_range<const _Vp>)
1752 return ranges::begin(_M_base);
1753 else
8f0d8cd8
PP
1754 {
1755 auto __sz = size();
1756 return counted_iterator{ranges::begin(_M_base), __sz};
1757 }
cba9ef06
PP
1758 }
1759 else
1760 return counted_iterator{ranges::begin(_M_base), _M_count};
1761 }
1762
1763 constexpr auto
1764 end() requires (!__detail::__simple_view<_Vp>)
1765 {
1766 if constexpr (sized_range<_Vp>)
1767 {
1768 if constexpr (random_access_range<_Vp>)
1769 return ranges::begin(_M_base) + size();
1770 else
1771 return default_sentinel;
1772 }
1773 else
1774 return _Sentinel<false>{ranges::end(_M_base)};
1775 }
1776
1777 constexpr auto
1778 end() const requires range<const _Vp>
1779 {
1780 if constexpr (sized_range<const _Vp>)
1781 {
1782 if constexpr (random_access_range<const _Vp>)
1783 return ranges::begin(_M_base) + size();
1784 else
1785 return default_sentinel;
1786 }
1787 else
1788 return _Sentinel<true>{ranges::end(_M_base)};
1789 }
1790
1791 constexpr auto
1792 size() requires sized_range<_Vp>
1793 {
1794 auto __n = ranges::size(_M_base);
1795 return __detail::min(__n, static_cast<decltype(__n)>(_M_count));
1796 }
1797
1798 constexpr auto
1799 size() const requires sized_range<const _Vp>
1800 {
1801 auto __n = ranges::size(_M_base);
1802 return __detail::min(__n, static_cast<decltype(__n)>(_M_count));
1803 }
1804 };
1805
50106208
PP
1806 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1807 // 3447. Deduction guides for take_view and drop_view have different
1808 // constraints
1809 template<typename _Range>
cba9ef06 1810 take_view(_Range&&, range_difference_t<_Range>)
aca60ecf 1811 -> take_view<views::all_t<_Range>>;
cba9ef06 1812
39bf4f14
JW
1813 template<typename _Tp>
1814 inline constexpr bool enable_borrowed_range<take_view<_Tp>>
1815 = enable_borrowed_range<_Tp>;
1816
cba9ef06
PP
1817 namespace views
1818 {
1819 inline constexpr __adaptor::_RangeAdaptor take
1820 = [] <viewable_range _Range, typename _Tp> (_Range&& __r, _Tp&& __n)
1821 {
1822 return take_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)};
1823 };
1824 } // namespace views
1825
1826 template<view _Vp, typename _Pred>
1827 requires input_range<_Vp> && is_object_v<_Pred>
1828 && indirect_unary_predicate<const _Pred, iterator_t<_Vp>>
1829 class take_while_view : public view_interface<take_while_view<_Vp, _Pred>>
1830 {
1831 template<bool _Const>
1832 struct _Sentinel
1833 {
1834 private:
8017d95c 1835 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06
PP
1836
1837 sentinel_t<_Base> _M_end = sentinel_t<_Base>();
1838 const _Pred* _M_pred = nullptr;
1839
1840 public:
1841 _Sentinel() = default;
1842
1843 constexpr explicit
1844 _Sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
1845 : _M_end(__end), _M_pred(__pred)
1846 { }
1847
1848 constexpr
1849 _Sentinel(_Sentinel<!_Const> __s)
1850 requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>
1851 : _M_end(__s._M_end), _M_pred(__s._M_pred)
1852 { }
1853
1854 constexpr sentinel_t<_Base>
1855 base() const { return _M_end; }
1856
1857 friend constexpr bool
1858 operator==(const iterator_t<_Base>& __x, const _Sentinel& __y)
1859 { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); }
ba49e9eb 1860
e066821b
PP
1861 template<bool _OtherConst = !_Const,
1862 typename _Base2 = __detail::__maybe_const_t<_OtherConst, _Vp>>
1863 requires sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
1864 friend constexpr bool
1865 operator==(const iterator_t<_Base2>& __x, const _Sentinel& __y)
1866 { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); }
1867
ba49e9eb 1868 friend _Sentinel<!_Const>;
cba9ef06
PP
1869 };
1870
42907ca9 1871 [[no_unique_address]] __detail::__box<_Pred> _M_pred;
361e32ee 1872 _Vp _M_base = _Vp();
cba9ef06
PP
1873
1874 public:
1875 take_while_view() = default;
1876
1877 constexpr
1878 take_while_view(_Vp base, _Pred __pred)
361e32ee
PP
1879 : _M_pred(std::move(__pred)), _M_base(std::move(base))
1880 { }
cba9ef06
PP
1881
1882 constexpr _Vp
1883 base() const& requires copy_constructible<_Vp>
1884 { return _M_base; }
1885
1886 constexpr _Vp
1887 base() &&
1888 { return std::move(_M_base); }
1889
1890 constexpr const _Pred&
1891 pred() const
1892 { return *_M_pred; }
1893
1894 constexpr auto
1895 begin() requires (!__detail::__simple_view<_Vp>)
1896 { return ranges::begin(_M_base); }
1897
1898 constexpr auto
1899 begin() const requires range<const _Vp>
c5aad5a4 1900 && indirect_unary_predicate<const _Pred, iterator_t<const _Vp>>
cba9ef06
PP
1901 { return ranges::begin(_M_base); }
1902
1903 constexpr auto
1904 end() requires (!__detail::__simple_view<_Vp>)
1905 { return _Sentinel<false>(ranges::end(_M_base),
1906 std::__addressof(*_M_pred)); }
1907
1908 constexpr auto
1909 end() const requires range<const _Vp>
c5aad5a4 1910 && indirect_unary_predicate<const _Pred, iterator_t<const _Vp>>
cba9ef06
PP
1911 { return _Sentinel<true>(ranges::end(_M_base),
1912 std::__addressof(*_M_pred)); }
1913 };
1914
1915 template<typename _Range, typename _Pred>
1916 take_while_view(_Range&&, _Pred)
aca60ecf 1917 -> take_while_view<views::all_t<_Range>, _Pred>;
cba9ef06
PP
1918
1919 namespace views
1920 {
1921 inline constexpr __adaptor::_RangeAdaptor take_while
1922 = [] <viewable_range _Range, typename _Pred> (_Range&& __r, _Pred&& __p)
1923 {
1924 return take_while_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)};
1925 };
1926 } // namespace views
1927
1928 template<view _Vp>
1929 class drop_view : public view_interface<drop_view<_Vp>>
1930 {
1931 private:
7433536b 1932 range_difference_t<_Vp> _M_count = 0;
361e32ee 1933 _Vp _M_base = _Vp();
cba9ef06 1934
aecea415
JW
1935 // ranges::next(begin(base), count, end(base)) is O(1) if _Vp satisfies
1936 // both random_access_range and sized_range. Otherwise, cache its result.
1937 static constexpr bool _S_needs_cached_begin
1938 = !(random_access_range<const _Vp> && sized_range<const _Vp>);
a1535015 1939 [[no_unique_address]]
4c391563
JW
1940 __detail::__maybe_present_t<_S_needs_cached_begin,
1941 __detail::_CachedPosition<_Vp>>
1942 _M_cached_begin;
a1535015 1943
cba9ef06
PP
1944 public:
1945 drop_view() = default;
1946
1947 constexpr
1948 drop_view(_Vp __base, range_difference_t<_Vp> __count)
361e32ee 1949 : _M_count(__count), _M_base(std::move(__base))
cba9ef06
PP
1950 { __glibcxx_assert(__count >= 0); }
1951
1952 constexpr _Vp
1953 base() const& requires copy_constructible<_Vp>
1954 { return _M_base; }
1955
1956 constexpr _Vp
1957 base() &&
1958 { return std::move(_M_base); }
1959
aecea415 1960 // This overload is disabled for simple views with constant-time begin().
cba9ef06 1961 constexpr auto
aecea415
JW
1962 begin()
1963 requires (!(__detail::__simple_view<_Vp>
1964 && random_access_range<const _Vp>
1965 && sized_range<const _Vp>))
cba9ef06 1966 {
a1535015
PP
1967 if constexpr (_S_needs_cached_begin)
1968 if (_M_cached_begin._M_has_value())
1969 return _M_cached_begin._M_get(_M_base);
1970
1971 auto __it = ranges::next(ranges::begin(_M_base),
1972 _M_count, ranges::end(_M_base));
1973 if constexpr (_S_needs_cached_begin)
1974 _M_cached_begin._M_set(_M_base, __it);
1975 return __it;
cba9ef06
PP
1976 }
1977
aecea415
JW
1978 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1979 // 3482. drop_view's const begin should additionally require sized_range
cba9ef06 1980 constexpr auto
aecea415
JW
1981 begin() const
1982 requires random_access_range<const _Vp> && sized_range<const _Vp>
cba9ef06
PP
1983 {
1984 return ranges::next(ranges::begin(_M_base), _M_count,
1985 ranges::end(_M_base));
1986 }
1987
1988 constexpr auto
1989 end() requires (!__detail::__simple_view<_Vp>)
1990 { return ranges::end(_M_base); }
1991
1992 constexpr auto
1993 end() const requires range<const _Vp>
1994 { return ranges::end(_M_base); }
1995
1996 constexpr auto
1997 size() requires sized_range<_Vp>
1998 {
1999 const auto __s = ranges::size(_M_base);
2000 const auto __c = static_cast<decltype(__s)>(_M_count);
2001 return __s < __c ? 0 : __s - __c;
2002 }
2003
2004 constexpr auto
2005 size() const requires sized_range<const _Vp>
2006 {
2007 const auto __s = ranges::size(_M_base);
2008 const auto __c = static_cast<decltype(__s)>(_M_count);
2009 return __s < __c ? 0 : __s - __c;
2010 }
2011 };
2012
2013 template<typename _Range>
2014 drop_view(_Range&&, range_difference_t<_Range>)
aca60ecf 2015 -> drop_view<views::all_t<_Range>>;
cba9ef06 2016
39bf4f14
JW
2017 template<typename _Tp>
2018 inline constexpr bool enable_borrowed_range<drop_view<_Tp>>
2019 = enable_borrowed_range<_Tp>;
2020
cba9ef06
PP
2021 namespace views
2022 {
2023 inline constexpr __adaptor::_RangeAdaptor drop
2024 = [] <viewable_range _Range, typename _Tp> (_Range&& __r, _Tp&& __n)
2025 {
2026 return drop_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)};
2027 };
2028 } // namespace views
2029
2030 template<view _Vp, typename _Pred>
2031 requires input_range<_Vp> && is_object_v<_Pred>
2032 && indirect_unary_predicate<const _Pred, iterator_t<_Vp>>
2033 class drop_while_view : public view_interface<drop_while_view<_Vp, _Pred>>
2034 {
2035 private:
42907ca9 2036 [[no_unique_address]] __detail::__box<_Pred> _M_pred;
a1535015 2037 [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin;
361e32ee 2038 _Vp _M_base = _Vp();
cba9ef06
PP
2039
2040 public:
2041 drop_while_view() = default;
2042
2043 constexpr
2044 drop_while_view(_Vp __base, _Pred __pred)
361e32ee 2045 : _M_pred(std::move(__pred)), _M_base(std::move(__base))
cba9ef06
PP
2046 { }
2047
2048 constexpr _Vp
2049 base() const& requires copy_constructible<_Vp>
2050 { return _M_base; }
2051
2052 constexpr _Vp
2053 base() &&
2054 { return std::move(_M_base); }
2055
2056 constexpr const _Pred&
2057 pred() const
2058 { return *_M_pred; }
2059
2060 constexpr auto
2061 begin()
2062 {
a1535015
PP
2063 if (_M_cached_begin._M_has_value())
2064 return _M_cached_begin._M_get(_M_base);
2065
2066 auto __it = __detail::find_if_not(ranges::begin(_M_base),
2067 ranges::end(_M_base),
2068 std::cref(*_M_pred));
2069 _M_cached_begin._M_set(_M_base, __it);
2070 return __it;
cba9ef06
PP
2071 }
2072
2073 constexpr auto
2074 end()
2075 { return ranges::end(_M_base); }
2076 };
2077
2078 template<typename _Range, typename _Pred>
2079 drop_while_view(_Range&&, _Pred)
aca60ecf 2080 -> drop_while_view<views::all_t<_Range>, _Pred>;
cba9ef06 2081
39bf4f14
JW
2082 template<typename _Tp, typename _Pred>
2083 inline constexpr bool enable_borrowed_range<drop_while_view<_Tp, _Pred>>
2084 = enable_borrowed_range<_Tp>;
2085
cba9ef06
PP
2086 namespace views
2087 {
2088 inline constexpr __adaptor::_RangeAdaptor drop_while
2089 = [] <viewable_range _Range, typename _Pred> (_Range&& __r, _Pred&& __p)
2090 {
2091 return drop_while_view{std::forward<_Range>(__r),
2092 std::forward<_Pred>(__p)};
2093 };
2094 } // namespace views
2095
2096 template<input_range _Vp>
2097 requires view<_Vp> && input_range<range_reference_t<_Vp>>
2098 && (is_reference_v<range_reference_t<_Vp>>
2099 || view<range_value_t<_Vp>>)
2100 class join_view : public view_interface<join_view<_Vp>>
2101 {
2102 private:
2103 using _InnerRange = range_reference_t<_Vp>;
2104
2105 template<bool _Const>
2106 struct _Sentinel;
2107
2108 template<bool _Const>
2109 struct _Iterator
2110 {
2111 private:
8017d95c
JW
2112 using _Parent = __detail::__maybe_const_t<_Const, join_view>;
2113 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06
PP
2114
2115 static constexpr bool _S_ref_is_glvalue
2116 = is_reference_v<range_reference_t<_Base>>;
2117
2118 constexpr void
2119 _M_satisfy()
2120 {
2121 auto __update_inner = [this] (range_reference_t<_Base> __x) -> auto&
2122 {
2123 if constexpr (_S_ref_is_glvalue)
2124 return __x;
2125 else
2126 return (_M_parent->_M_inner = views::all(std::move(__x)));
2127 };
2128
2129 for (; _M_outer != ranges::end(_M_parent->_M_base); ++_M_outer)
2130 {
d4a788c7
PP
2131 auto& __inner = __update_inner(*_M_outer);
2132 _M_inner = ranges::begin(__inner);
2133 if (_M_inner != ranges::end(__inner))
cba9ef06
PP
2134 return;
2135 }
2136
2137 if constexpr (_S_ref_is_glvalue)
a5b213dd 2138 _M_inner = _Inner_iter();
cba9ef06
PP
2139 }
2140
2141 static constexpr auto
2142 _S_iter_concept()
2143 {
2144 if constexpr (_S_ref_is_glvalue
2145 && bidirectional_range<_Base>
2146 && bidirectional_range<range_reference_t<_Base>>)
2147 return bidirectional_iterator_tag{};
2148 else if constexpr (_S_ref_is_glvalue
2149 && forward_range<_Base>
2150 && forward_range<range_reference_t<_Base>>)
2151 return forward_iterator_tag{};
2152 else
2153 return input_iterator_tag{};
2154 }
2155
2156 static constexpr auto
2157 _S_iter_cat()
2158 {
2159 using _OuterCat
a5b213dd 2160 = typename iterator_traits<_Outer_iter>::iterator_category;
cba9ef06 2161 using _InnerCat
a5b213dd 2162 = typename iterator_traits<_Inner_iter>::iterator_category;
cba9ef06
PP
2163 if constexpr (_S_ref_is_glvalue
2164 && derived_from<_OuterCat, bidirectional_iterator_tag>
2165 && derived_from<_InnerCat, bidirectional_iterator_tag>)
2166 return bidirectional_iterator_tag{};
2167 else if constexpr (_S_ref_is_glvalue
2168 && derived_from<_OuterCat, forward_iterator_tag>
2169 && derived_from<_InnerCat, forward_iterator_tag>)
2170 return forward_iterator_tag{};
2171 else if constexpr (derived_from<_OuterCat, input_iterator_tag>
2172 && derived_from<_InnerCat, input_iterator_tag>)
2173 return input_iterator_tag{};
2174 else
2175 return output_iterator_tag{};
2176 }
2177
a5b213dd
JW
2178 using _Outer_iter = iterator_t<_Base>;
2179 using _Inner_iter = iterator_t<range_reference_t<_Base>>;
2180
2181 _Outer_iter _M_outer = _Outer_iter();
2182 _Inner_iter _M_inner = _Inner_iter();
cba9ef06
PP
2183 _Parent* _M_parent = nullptr;
2184
2185 public:
2186 using iterator_concept = decltype(_S_iter_concept());
2187 using iterator_category = decltype(_S_iter_cat());
2188 using value_type = range_value_t<range_reference_t<_Base>>;
2189 using difference_type
2190 = common_type_t<range_difference_t<_Base>,
2191 range_difference_t<range_reference_t<_Base>>>;
2192
2193 _Iterator() = default;
2194
cba9ef06 2195 constexpr
afb8da7f 2196 _Iterator(_Parent* __parent, _Outer_iter __outer)
cba9ef06 2197 : _M_outer(std::move(__outer)),
afb8da7f 2198 _M_parent(__parent)
cba9ef06
PP
2199 { _M_satisfy(); }
2200
2201 constexpr
2202 _Iterator(_Iterator<!_Const> __i)
2203 requires _Const
a5b213dd
JW
2204 && convertible_to<iterator_t<_Vp>, _Outer_iter>
2205 && convertible_to<iterator_t<_InnerRange>, _Inner_iter>
cba9ef06
PP
2206 : _M_outer(std::move(__i._M_outer)), _M_inner(__i._M_inner),
2207 _M_parent(__i._M_parent)
2208 { }
2209
2210 constexpr decltype(auto)
2211 operator*() const
2212 { return *_M_inner; }
2213
d4a788c7
PP
2214 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2215 // 3500. join_view::iterator::operator->() is bogus
2216 constexpr _Inner_iter
cba9ef06 2217 operator->() const
d4a788c7
PP
2218 requires __detail::__has_arrow<_Inner_iter>
2219 && copyable<_Inner_iter>
cba9ef06
PP
2220 { return _M_inner; }
2221
2222 constexpr _Iterator&
2223 operator++()
2224 {
2225 auto&& __inner_range = [this] () -> decltype(auto) {
2226 if constexpr (_S_ref_is_glvalue)
2227 return *_M_outer;
2228 else
2229 return _M_parent->_M_inner;
2230 }();
2231 if (++_M_inner == ranges::end(__inner_range))
2232 {
2233 ++_M_outer;
2234 _M_satisfy();
2235 }
2236 return *this;
2237 }
2238
2239 constexpr void
2240 operator++(int)
2241 { ++*this; }
2242
2243 constexpr _Iterator
2244 operator++(int)
2245 requires _S_ref_is_glvalue && forward_range<_Base>
2246 && forward_range<range_reference_t<_Base>>
2247 {
2248 auto __tmp = *this;
2249 ++*this;
2250 return __tmp;
2251 }
2252
2253 constexpr _Iterator&
2254 operator--()
2255 requires _S_ref_is_glvalue && bidirectional_range<_Base>
2256 && bidirectional_range<range_reference_t<_Base>>
55c4b3f4 2257 && common_range<range_reference_t<_Base>>
cba9ef06
PP
2258 {
2259 if (_M_outer == ranges::end(_M_parent->_M_base))
2260 _M_inner = ranges::end(*--_M_outer);
2261 while (_M_inner == ranges::begin(*_M_outer))
2262 _M_inner = ranges::end(*--_M_outer);
2263 --_M_inner;
2264 return *this;
2265 }
2266
2267 constexpr _Iterator
2268 operator--(int)
2269 requires _S_ref_is_glvalue && bidirectional_range<_Base>
2270 && bidirectional_range<range_reference_t<_Base>>
55c4b3f4 2271 && common_range<range_reference_t<_Base>>
cba9ef06
PP
2272 {
2273 auto __tmp = *this;
2274 --*this;
2275 return __tmp;
2276 }
2277
2278 friend constexpr bool
2279 operator==(const _Iterator& __x, const _Iterator& __y)
2280 requires _S_ref_is_glvalue
a5b213dd
JW
2281 && equality_comparable<_Outer_iter>
2282 && equality_comparable<_Inner_iter>
cba9ef06
PP
2283 {
2284 return (__x._M_outer == __y._M_outer
2285 && __x._M_inner == __y._M_inner);
2286 }
2287
2288 friend constexpr decltype(auto)
2289 iter_move(const _Iterator& __i)
2290 noexcept(noexcept(ranges::iter_move(__i._M_inner)))
2291 { return ranges::iter_move(__i._M_inner); }
2292
2293 friend constexpr void
2294 iter_swap(const _Iterator& __x, const _Iterator& __y)
2295 noexcept(noexcept(ranges::iter_swap(__x._M_inner, __y._M_inner)))
2296 { return ranges::iter_swap(__x._M_inner, __y._M_inner); }
2297
242b4fb7 2298 friend _Iterator<!_Const>;
6c2582c0 2299 template<bool> friend struct _Sentinel;
cba9ef06
PP
2300 };
2301
2302 template<bool _Const>
2303 struct _Sentinel
2304 {
2305 private:
8017d95c
JW
2306 using _Parent = __detail::__maybe_const_t<_Const, join_view>;
2307 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06 2308
6c2582c0
JW
2309 template<bool _Const2>
2310 constexpr bool
2311 __equal(const _Iterator<_Const2>& __i) const
2312 { return __i._M_outer == _M_end; }
cba9ef06
PP
2313
2314 sentinel_t<_Base> _M_end = sentinel_t<_Base>();
2315
2316 public:
2317 _Sentinel() = default;
2318
2319 constexpr explicit
afb8da7f
PP
2320 _Sentinel(_Parent* __parent)
2321 : _M_end(ranges::end(__parent->_M_base))
cba9ef06
PP
2322 { }
2323
2324 constexpr
2325 _Sentinel(_Sentinel<!_Const> __s)
2326 requires _Const && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>
2327 : _M_end(std::move(__s._M_end))
2328 { }
2329
6c2582c0
JW
2330 template<bool _Const2>
2331 requires sentinel_for<sentinel_t<_Base>,
2332 iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>>
2333 friend constexpr bool
2334 operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)
2335 { return __y.__equal(__x); }
6aa2ca21
PP
2336
2337 friend _Sentinel<!_Const>;
cba9ef06
PP
2338 };
2339
cba9ef06 2340 // XXX: _M_inner is "present only when !is_reference_v<_InnerRange>"
242b4fb7 2341 [[no_unique_address]]
4c391563
JW
2342 __detail::__maybe_present_t<!is_reference_v<_InnerRange>,
2343 views::all_t<_InnerRange>> _M_inner;
361e32ee 2344 _Vp _M_base = _Vp();
cba9ef06
PP
2345
2346 public:
2347 join_view() = default;
2348
2349 constexpr explicit
2350 join_view(_Vp __base)
2351 : _M_base(std::move(__base))
2352 { }
2353
cba9ef06
PP
2354 constexpr _Vp
2355 base() const& requires copy_constructible<_Vp>
2356 { return _M_base; }
2357
2358 constexpr _Vp
2359 base() &&
2360 { return std::move(_M_base); }
2361
2362 constexpr auto
2363 begin()
2364 {
242b4fb7
PP
2365 constexpr bool __use_const
2366 = (__detail::__simple_view<_Vp>
2367 && is_reference_v<range_reference_t<_Vp>>);
afb8da7f 2368 return _Iterator<__use_const>{this, ranges::begin(_M_base)};
cba9ef06
PP
2369 }
2370
2371 constexpr auto
2372 begin() const
2373 requires input_range<const _Vp>
2374 && is_reference_v<range_reference_t<const _Vp>>
2375 {
afb8da7f 2376 return _Iterator<true>{this, ranges::begin(_M_base)};
cba9ef06
PP
2377 }
2378
2379 constexpr auto
2380 end()
2381 {
2382 if constexpr (forward_range<_Vp> && is_reference_v<_InnerRange>
2383 && forward_range<_InnerRange>
2384 && common_range<_Vp> && common_range<_InnerRange>)
afb8da7f 2385 return _Iterator<__detail::__simple_view<_Vp>>{this,
cba9ef06
PP
2386 ranges::end(_M_base)};
2387 else
afb8da7f 2388 return _Sentinel<__detail::__simple_view<_Vp>>{this};
cba9ef06
PP
2389 }
2390
2391 constexpr auto
2392 end() const
2393 requires input_range<const _Vp>
2394 && is_reference_v<range_reference_t<const _Vp>>
2395 {
2396 if constexpr (forward_range<const _Vp>
2397 && is_reference_v<range_reference_t<const _Vp>>
2398 && forward_range<range_reference_t<const _Vp>>
2399 && common_range<const _Vp>
2400 && common_range<range_reference_t<const _Vp>>)
afb8da7f 2401 return _Iterator<true>{this, ranges::end(_M_base)};
cba9ef06 2402 else
afb8da7f 2403 return _Sentinel<true>{this};
cba9ef06
PP
2404 }
2405 };
2406
2407 template<typename _Range>
aca60ecf 2408 explicit join_view(_Range&&) -> join_view<views::all_t<_Range>>;
cba9ef06
PP
2409
2410 namespace views
2411 {
2412 inline constexpr __adaptor::_RangeAdaptorClosure join
2413 = [] <viewable_range _Range> (_Range&& __r)
2414 {
9065c4ad
JW
2415 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2416 // 3474. Nesting join_views is broken because of CTAD
2417 return join_view<views::all_t<_Range>>{std::forward<_Range>(__r)};
cba9ef06
PP
2418 };
2419 } // namespace views
2420
2421 namespace __detail
2422 {
2423 template<auto>
2424 struct __require_constant;
2425
2426 template<typename _Range>
2427 concept __tiny_range = sized_range<_Range>
2428 && requires
2429 { typename __require_constant<remove_reference_t<_Range>::size()>; }
2430 && (remove_reference_t<_Range>::size() <= 1);
2431 }
2432
2433 template<input_range _Vp, forward_range _Pattern>
2434 requires view<_Vp> && view<_Pattern>
2435 && indirectly_comparable<iterator_t<_Vp>, iterator_t<_Pattern>,
2436 ranges::equal_to>
2437 && (forward_range<_Vp> || __detail::__tiny_range<_Pattern>)
2438 class split_view : public view_interface<split_view<_Vp, _Pattern>>
2439 {
2440 private:
2441 template<bool _Const>
2442 struct _InnerIter;
2443
2444 template<bool _Const>
2445 struct _OuterIter
2446 {
2447 private:
8017d95c
JW
2448 using _Parent = __detail::__maybe_const_t<_Const, split_view>;
2449 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06
PP
2450
2451 constexpr bool
2452 __at_end() const
0b7f1e24 2453 { return __current() == ranges::end(_M_parent->_M_base); }
cba9ef06 2454
0b7f1e24 2455 // [range.split.outer] p1
cba9ef06 2456 // Many of the following specifications refer to the notional member
97a7c229
JW
2457 // current of outer-iterator. current is equivalent to current_ if
2458 // V models forward_range, and parent_->current_ otherwise.
cba9ef06 2459 constexpr auto&
cf0c3a45 2460 __current() noexcept
cba9ef06
PP
2461 {
2462 if constexpr (forward_range<_Vp>)
2463 return _M_current;
2464 else
2465 return _M_parent->_M_current;
2466 }
2467
2468 constexpr auto&
cf0c3a45 2469 __current() const noexcept
cba9ef06
PP
2470 {
2471 if constexpr (forward_range<_Vp>)
2472 return _M_current;
2473 else
2474 return _M_parent->_M_current;
2475 }
2476
2477 _Parent* _M_parent = nullptr;
2478
2479 // XXX: _M_current is present only if "V models forward_range"
2480 [[no_unique_address]]
4c391563
JW
2481 __detail::__maybe_present_t<forward_range<_Vp>,
2482 iterator_t<_Base>> _M_current;
cba9ef06
PP
2483
2484 public:
2485 using iterator_concept = conditional_t<forward_range<_Base>,
2486 forward_iterator_tag,
2487 input_iterator_tag>;
2488 using iterator_category = input_iterator_tag;
2489 using difference_type = range_difference_t<_Base>;
2490
2491 struct value_type : view_interface<value_type>
2492 {
2493 private:
2494 _OuterIter _M_i = _OuterIter();
2495
2496 public:
2497 value_type() = default;
2498
2499 constexpr explicit
2500 value_type(_OuterIter __i)
2501 : _M_i(std::move(__i))
2502 { }
2503
2504 constexpr _InnerIter<_Const>
2505 begin() const
2506 requires copyable<_OuterIter>
2507 { return _InnerIter<_Const>{_M_i}; }
2508
2509 constexpr _InnerIter<_Const>
2510 begin()
2511 requires (!copyable<_OuterIter>)
2512 { return _InnerIter<_Const>{std::move(_M_i)}; }
2513
2514 constexpr default_sentinel_t
2515 end() const
2516 { return default_sentinel; }
2517 };
2518
2519 _OuterIter() = default;
2520
2521 constexpr explicit
afb8da7f
PP
2522 _OuterIter(_Parent* __parent) requires (!forward_range<_Base>)
2523 : _M_parent(__parent)
cba9ef06
PP
2524 { }
2525
2526 constexpr
afb8da7f 2527 _OuterIter(_Parent* __parent, iterator_t<_Base> __current)
cba9ef06 2528 requires forward_range<_Base>
afb8da7f 2529 : _M_parent(__parent),
cba9ef06
PP
2530 _M_current(std::move(__current))
2531 { }
2532
2533 constexpr
2534 _OuterIter(_OuterIter<!_Const> __i)
2535 requires _Const
242b4fb7 2536 && convertible_to<iterator_t<_Vp>, iterator_t<_Base>>
cba9ef06
PP
2537 : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current))
2538 { }
2539
2540 constexpr value_type
2541 operator*() const
2542 { return value_type{*this}; }
2543
2544 constexpr _OuterIter&
2545 operator++()
2546 {
2547 const auto __end = ranges::end(_M_parent->_M_base);
0b7f1e24 2548 if (__current() == __end)
cba9ef06
PP
2549 return *this;
2550 const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern};
2551 if (__pbegin == __pend)
0b7f1e24 2552 ++__current();
cba9ef06
PP
2553 else
2554 do
2555 {
2556 auto [__b, __p]
0b7f1e24 2557 = __detail::mismatch(std::move(__current()), __end,
cba9ef06 2558 __pbegin, __pend);
0b7f1e24 2559 __current() = std::move(__b);
cba9ef06
PP
2560 if (__p == __pend)
2561 break;
0b7f1e24 2562 } while (++__current() != __end);
cba9ef06
PP
2563 return *this;
2564 }
2565
2566 constexpr decltype(auto)
2567 operator++(int)
2568 {
2569 if constexpr (forward_range<_Base>)
2570 {
2571 auto __tmp = *this;
2572 ++*this;
2573 return __tmp;
2574 }
2575 else
2576 ++*this;
2577 }
2578
2579 friend constexpr bool
2580 operator==(const _OuterIter& __x, const _OuterIter& __y)
2581 requires forward_range<_Base>
2582 { return __x._M_current == __y._M_current; }
2583
2584 friend constexpr bool
2585 operator==(const _OuterIter& __x, default_sentinel_t)
2586 { return __x.__at_end(); };
2587
ba49e9eb 2588 friend _OuterIter<!_Const>;
cba9ef06
PP
2589 friend _InnerIter<_Const>;
2590 };
2591
2592 template<bool _Const>
2593 struct _InnerIter
2594 {
2595 private:
8017d95c 2596 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06
PP
2597
2598 constexpr bool
2599 __at_end() const
2600 {
2601 auto [__pcur, __pend] = subrange{_M_i._M_parent->_M_pattern};
2602 auto __end = ranges::end(_M_i._M_parent->_M_base);
2603 if constexpr (__detail::__tiny_range<_Pattern>)
2604 {
cf0c3a45 2605 const auto& __cur = _M_i_current();
cba9ef06
PP
2606 if (__cur == __end)
2607 return true;
2608 if (__pcur == __pend)
2609 return _M_incremented;
2610 return *__cur == *__pcur;
2611 }
2612 else
2613 {
cf0c3a45 2614 auto __cur = _M_i_current();
cba9ef06
PP
2615 if (__cur == __end)
2616 return true;
2617 if (__pcur == __pend)
2618 return _M_incremented;
2619 do
2620 {
2621 if (*__cur != *__pcur)
2622 return false;
2623 if (++__pcur == __pend)
2624 return true;
2625 } while (++__cur != __end);
2626 return false;
2627 }
2628 }
2629
2630 static constexpr auto
2631 _S_iter_cat()
2632 {
a5b213dd
JW
2633 using _Cat
2634 = typename iterator_traits<iterator_t<_Base>>::iterator_category;
cba9ef06
PP
2635 if constexpr (derived_from<_Cat, forward_iterator_tag>)
2636 return forward_iterator_tag{};
2637 else
2638 return _Cat{};
2639 }
2640
cf0c3a45
JW
2641 constexpr auto&
2642 _M_i_current() noexcept
2643 { return _M_i.__current(); }
cba9ef06 2644
cf0c3a45
JW
2645 constexpr auto&
2646 _M_i_current() const noexcept
2647 { return _M_i.__current(); }
cba9ef06
PP
2648
2649 _OuterIter<_Const> _M_i = _OuterIter<_Const>();
2650 bool _M_incremented = false;
2651
2652 public:
a5b213dd
JW
2653 using iterator_concept
2654 = typename _OuterIter<_Const>::iterator_concept;
cba9ef06
PP
2655 using iterator_category = decltype(_S_iter_cat());
2656 using value_type = range_value_t<_Base>;
2657 using difference_type = range_difference_t<_Base>;
2658
2659 _InnerIter() = default;
2660
2661 constexpr explicit
2662 _InnerIter(_OuterIter<_Const> __i)
2663 : _M_i(std::move(__i))
2664 { }
2665
2666 constexpr decltype(auto)
2667 operator*() const
cf0c3a45 2668 { return *_M_i_current(); }
cba9ef06
PP
2669
2670 constexpr _InnerIter&
2671 operator++()
2672 {
2673 _M_incremented = true;
2674 if constexpr (!forward_range<_Base>)
2675 if constexpr (_Pattern::size() == 0)
2676 return *this;
cf0c3a45 2677 ++_M_i_current();
cba9ef06
PP
2678 return *this;
2679 }
2680
2681 constexpr decltype(auto)
2682 operator++(int)
2683 {
2684 if constexpr (forward_range<_Vp>)
2685 {
2686 auto __tmp = *this;
2687 ++*this;
2688 return __tmp;
2689 }
2690 else
2691 ++*this;
2692 }
2693
2694 friend constexpr bool
2695 operator==(const _InnerIter& __x, const _InnerIter& __y)
2696 requires forward_range<_Base>
8ce13842 2697 { return __x._M_i == __y._M_i; }
cba9ef06
PP
2698
2699 friend constexpr bool
2700 operator==(const _InnerIter& __x, default_sentinel_t)
2701 { return __x.__at_end(); }
2702
2703 friend constexpr decltype(auto)
cf0c3a45
JW
2704 iter_move(const _InnerIter& __i)
2705 noexcept(noexcept(ranges::iter_move(__i._M_i_current())))
2706 { return ranges::iter_move(__i._M_i_current()); }
cba9ef06
PP
2707
2708 friend constexpr void
2709 iter_swap(const _InnerIter& __x, const _InnerIter& __y)
cf0c3a45
JW
2710 noexcept(noexcept(ranges::iter_swap(__x._M_i_current(),
2711 __y._M_i_current())))
cba9ef06 2712 requires indirectly_swappable<iterator_t<_Base>>
cf0c3a45 2713 { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); }
cba9ef06
PP
2714 };
2715
cba9ef06 2716 _Pattern _M_pattern = _Pattern();
cba9ef06
PP
2717 // XXX: _M_current is "present only if !forward_range<V>"
2718 [[no_unique_address]]
361e32ee
PP
2719 __detail::__maybe_present_t<!forward_range<_Vp>,
2720 iterator_t<_Vp>> _M_current;
2721 _Vp _M_base = _Vp();
cba9ef06
PP
2722
2723
2724 public:
2725 split_view() = default;
2726
2727 constexpr
2728 split_view(_Vp __base, _Pattern __pattern)
361e32ee 2729 : _M_pattern(std::move(__pattern)), _M_base(std::move(__base))
cba9ef06
PP
2730 { }
2731
cba9ef06 2732 template<input_range _Range>
aca60ecf 2733 requires constructible_from<_Vp, views::all_t<_Range>>
cba9ef06
PP
2734 && constructible_from<_Pattern, single_view<range_value_t<_Range>>>
2735 constexpr
2736 split_view(_Range&& __r, range_value_t<_Range> __e)
361e32ee
PP
2737 : _M_pattern(std::move(__e)),
2738 _M_base(views::all(std::forward<_Range>(__r)))
cba9ef06
PP
2739 { }
2740
2741 constexpr _Vp
2742 base() const& requires copy_constructible<_Vp>
2743 { return _M_base; }
2744
2745 constexpr _Vp
2746 base() &&
2747 { return std::move(_M_base); }
2748
2749 constexpr auto
2750 begin()
2751 {
2752 if constexpr (forward_range<_Vp>)
cf0c3a45 2753 return _OuterIter<__detail::__simple_view<_Vp>>{
afb8da7f 2754 this, ranges::begin(_M_base)};
cba9ef06
PP
2755 else
2756 {
2757 _M_current = ranges::begin(_M_base);
afb8da7f 2758 return _OuterIter<false>{this};
cba9ef06
PP
2759 }
2760 }
2761
2762 constexpr auto
2763 begin() const requires forward_range<_Vp> && forward_range<const _Vp>
2764 {
afb8da7f 2765 return _OuterIter<true>{this, ranges::begin(_M_base)};
cba9ef06
PP
2766 }
2767
2768 constexpr auto
2769 end() requires forward_range<_Vp> && common_range<_Vp>
2770 {
cf0c3a45 2771 return _OuterIter<__detail::__simple_view<_Vp>>{
afb8da7f 2772 this, ranges::end(_M_base)};
cba9ef06
PP
2773 }
2774
2775 constexpr auto
2776 end() const
2777 {
2778 if constexpr (forward_range<_Vp>
2779 && forward_range<const _Vp>
2780 && common_range<const _Vp>)
afb8da7f 2781 return _OuterIter<true>{this, ranges::end(_M_base)};
cba9ef06
PP
2782 else
2783 return default_sentinel;
2784 }
2785 };
2786
2787 template<typename _Range, typename _Pred>
2788 split_view(_Range&&, _Pred&&)
aca60ecf 2789 -> split_view<views::all_t<_Range>, views::all_t<_Pred>>;
cba9ef06
PP
2790
2791 template<input_range _Range>
2792 split_view(_Range&&, range_value_t<_Range>)
aca60ecf 2793 -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
cba9ef06
PP
2794
2795 namespace views
2796 {
2797 inline constexpr __adaptor::_RangeAdaptor split
2798 = [] <viewable_range _Range, typename _Fp> (_Range&& __r, _Fp&& __f)
2799 {
2800 return split_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)};
2801 };
2802 } // namespace views
2803
2804 namespace views
2805 {
2806 struct _Counted
2807 {
2808 template<input_or_output_iterator _Iter>
2809 constexpr auto
2810 operator()(_Iter __i, iter_difference_t<_Iter> __n) const
2811 {
2812 if constexpr (random_access_iterator<_Iter>)
2813 return subrange{__i, __i + __n};
2814 else
2815 return subrange{counted_iterator{std::move(__i), __n},
2816 default_sentinel};
2817 }
2818 };
2819
2820 inline constexpr _Counted counted{};
2821 } // namespace views
2822
2823 template<view _Vp>
2824 requires (!common_range<_Vp>) && copyable<iterator_t<_Vp>>
2825 class common_view : public view_interface<common_view<_Vp>>
2826 {
2827 private:
2828 _Vp _M_base = _Vp();
2829
2830 public:
2831 common_view() = default;
2832
2833 constexpr explicit
2834 common_view(_Vp __r)
2835 : _M_base(std::move(__r))
2836 { }
2837
4cc3b275 2838 /* XXX: LWG 3280 didn't remove this constructor, but I think it should?
cba9ef06 2839 template<viewable_range _Range>
4cc3b275 2840 requires (!common_range<_Range>)
aca60ecf 2841 && constructible_from<_Vp, views::all_t<_Range>>
cba9ef06
PP
2842 constexpr explicit
2843 common_view(_Range&& __r)
2844 : _M_base(views::all(std::forward<_Range>(__r)))
2845 { }
4cc3b275 2846 */
cba9ef06
PP
2847
2848 constexpr _Vp
2849 base() const& requires copy_constructible<_Vp>
2850 { return _M_base; }
2851
2852 constexpr _Vp
2853 base() &&
2854 { return std::move(_M_base); }
2855
2856 constexpr auto
2857 begin()
2858 {
2859 if constexpr (random_access_range<_Vp> && sized_range<_Vp>)
2860 return ranges::begin(_M_base);
2861 else
2862 return common_iterator<iterator_t<_Vp>, sentinel_t<_Vp>>
2863 (ranges::begin(_M_base));
2864 }
2865
2866 constexpr auto
2867 begin() const requires range<const _Vp>
2868 {
2869 if constexpr (random_access_range<const _Vp> && sized_range<const _Vp>)
2870 return ranges::begin(_M_base);
2871 else
2872 return common_iterator<iterator_t<const _Vp>, sentinel_t<const _Vp>>
2873 (ranges::begin(_M_base));
2874 }
2875
2876 constexpr auto
2877 end()
2878 {
2879 if constexpr (random_access_range<_Vp> && sized_range<_Vp>)
2880 return ranges::begin(_M_base) + ranges::size(_M_base);
2881 else
2882 return common_iterator<iterator_t<_Vp>, sentinel_t<_Vp>>
2883 (ranges::end(_M_base));
2884 }
2885
2886 constexpr auto
2887 end() const requires range<const _Vp>
2888 {
2889 if constexpr (random_access_range<const _Vp> && sized_range<const _Vp>)
2890 return ranges::begin(_M_base) + ranges::size(_M_base);
2891 else
2892 return common_iterator<iterator_t<const _Vp>, sentinel_t<const _Vp>>
2893 (ranges::end(_M_base));
2894 }
2895
2896 constexpr auto
2897 size() requires sized_range<_Vp>
2898 { return ranges::size(_M_base); }
2899
2900 constexpr auto
2901 size() const requires sized_range<const _Vp>
2902 { return ranges::size(_M_base); }
2903 };
2904
2905 template<typename _Range>
aca60ecf 2906 common_view(_Range&&) -> common_view<views::all_t<_Range>>;
cba9ef06 2907
39bf4f14
JW
2908 template<typename _Tp>
2909 inline constexpr bool enable_borrowed_range<common_view<_Tp>>
2910 = enable_borrowed_range<_Tp>;
2911
cba9ef06
PP
2912 namespace views
2913 {
2914 inline constexpr __adaptor::_RangeAdaptorClosure common
2915 = [] <viewable_range _Range> (_Range&& __r)
2916 {
2917 if constexpr (common_range<_Range>
2918 && requires { views::all(std::forward<_Range>(__r)); })
2919 return views::all(std::forward<_Range>(__r));
2920 else
2921 return common_view{std::forward<_Range>(__r)};
2922 };
2923
2924 } // namespace views
2925
2926 template<view _Vp>
2927 requires bidirectional_range<_Vp>
2928 class reverse_view : public view_interface<reverse_view<_Vp>>
2929 {
2930 private:
77e596cf
PP
2931 static constexpr bool _S_needs_cached_begin
2932 = !common_range<_Vp> && !random_access_range<_Vp>;
361e32ee 2933
a1535015 2934 [[no_unique_address]]
4c391563
JW
2935 __detail::__maybe_present_t<_S_needs_cached_begin,
2936 __detail::_CachedPosition<_Vp>>
2937 _M_cached_begin;
361e32ee 2938 _Vp _M_base = _Vp();
a1535015 2939
cba9ef06
PP
2940 public:
2941 reverse_view() = default;
2942
2943 constexpr explicit
2944 reverse_view(_Vp __r)
2945 : _M_base(std::move(__r))
2946 { }
2947
cba9ef06
PP
2948 constexpr _Vp
2949 base() const& requires copy_constructible<_Vp>
2950 { return _M_base; }
2951
2952 constexpr _Vp
2953 base() &&
2954 { return std::move(_M_base); }
2955
2956 constexpr reverse_iterator<iterator_t<_Vp>>
2957 begin()
2958 {
a1535015
PP
2959 if constexpr (_S_needs_cached_begin)
2960 if (_M_cached_begin._M_has_value())
2961 return make_reverse_iterator(_M_cached_begin._M_get(_M_base));
2962
2963 auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base));
2964 if constexpr (_S_needs_cached_begin)
2965 _M_cached_begin._M_set(_M_base, __it);
2966 return make_reverse_iterator(std::move(__it));
cba9ef06
PP
2967 }
2968
2969 constexpr auto
2970 begin() requires common_range<_Vp>
2971 { return make_reverse_iterator(ranges::end(_M_base)); }
2972
2973 constexpr auto
2974 begin() const requires common_range<const _Vp>
2975 { return make_reverse_iterator(ranges::end(_M_base)); }
2976
2977 constexpr reverse_iterator<iterator_t<_Vp>>
2978 end()
2979 { return make_reverse_iterator(ranges::begin(_M_base)); }
2980
2981 constexpr auto
2982 end() const requires common_range<const _Vp>
2983 { return make_reverse_iterator(ranges::begin(_M_base)); }
2984
2985 constexpr auto
2986 size() requires sized_range<_Vp>
2987 { return ranges::size(_M_base); }
2988
2989 constexpr auto
2990 size() const requires sized_range<const _Vp>
2991 { return ranges::size(_M_base); }
2992 };
2993
2994 template<typename _Range>
aca60ecf 2995 reverse_view(_Range&&) -> reverse_view<views::all_t<_Range>>;
cba9ef06 2996
39bf4f14
JW
2997 template<typename _Tp>
2998 inline constexpr bool enable_borrowed_range<reverse_view<_Tp>>
2999 = enable_borrowed_range<_Tp>;
3000
cba9ef06
PP
3001 namespace views
3002 {
3003 namespace __detail
3004 {
3005 template<typename>
3006 inline constexpr bool __is_reversible_subrange = false;
3007
3008 template<typename _Iter, subrange_kind _Kind>
3009 inline constexpr bool
3010 __is_reversible_subrange<subrange<reverse_iterator<_Iter>,
3011 reverse_iterator<_Iter>,
3012 _Kind>> = true;
3013
3014 template<typename>
3015 inline constexpr bool __is_reverse_view = false;
3016
3017 template<typename _Vp>
3018 inline constexpr bool __is_reverse_view<reverse_view<_Vp>> = true;
3019 }
3020
3021 inline constexpr __adaptor::_RangeAdaptorClosure reverse
3022 = [] <viewable_range _Range> (_Range&& __r)
3023 {
3024 using _Tp = remove_cvref_t<_Range>;
3025 if constexpr (__detail::__is_reverse_view<_Tp>)
3026 return std::forward<_Range>(__r).base();
3027 else if constexpr (__detail::__is_reversible_subrange<_Tp>)
3028 {
3029 using _Iter = decltype(ranges::begin(__r).base());
3030 if constexpr (sized_range<_Tp>)
3031 return subrange<_Iter, _Iter, subrange_kind::sized>
3032 (__r.end().base(), __r.begin().base(), __r.size());
3033 else
3034 return subrange<_Iter, _Iter, subrange_kind::unsized>
3035 (__r.end().base(), __r.begin().base());
3036 }
3037 else
3038 return reverse_view{std::forward<_Range>(__r)};
3039 };
3040 } // namespace views
3041
3042 namespace __detail
3043 {
3044 template<typename _Tp, size_t _Nm>
3045 concept __has_tuple_element = requires(_Tp __t)
3046 {
3047 typename tuple_size<_Tp>::type;
3048 requires _Nm < tuple_size_v<_Tp>;
3049 typename tuple_element_t<_Nm, _Tp>;
cba9ef06
PP
3050 { std::get<_Nm>(__t) }
3051 -> convertible_to<const tuple_element_t<_Nm, _Tp>&>;
3052 };
3053 }
3054
3055 template<input_range _Vp, size_t _Nm>
3056 requires view<_Vp>
3057 && __detail::__has_tuple_element<range_value_t<_Vp>, _Nm>
3058 && __detail::__has_tuple_element<remove_reference_t<range_reference_t<_Vp>>,
3059 _Nm>
3060 class elements_view : public view_interface<elements_view<_Vp, _Nm>>
3061 {
3062 public:
3063 elements_view() = default;
3064
3065 constexpr explicit
3066 elements_view(_Vp base)
3067 : _M_base(std::move(base))
3068 { }
3069
3070 constexpr _Vp
3071 base() const& requires copy_constructible<_Vp>
3072 { return _M_base; }
3073
3074 constexpr _Vp
3075 base() &&
3076 { return std::move(_M_base); }
3077
3078 constexpr auto
3079 begin() requires (!__detail::__simple_view<_Vp>)
3080 { return _Iterator<false>(ranges::begin(_M_base)); }
3081
3082 constexpr auto
4be16d1c 3083 begin() const requires range<const _Vp>
cba9ef06
PP
3084 { return _Iterator<true>(ranges::begin(_M_base)); }
3085
3086 constexpr auto
4be16d1c 3087 end() requires (!__detail::__simple_view<_Vp> && !common_range<_Vp>)
97ab5daa 3088 { return _Sentinel<false>{ranges::end(_M_base)}; }
cba9ef06
PP
3089
3090 constexpr auto
4be16d1c 3091 end() requires (!__detail::__simple_view<_Vp> && common_range<_Vp>)
97ab5daa
PP
3092 { return _Iterator<false>{ranges::end(_M_base)}; }
3093
3094 constexpr auto
3095 end() const requires range<const _Vp>
3096 { return _Sentinel<true>{ranges::end(_M_base)}; }
3097
3098 constexpr auto
3099 end() const requires common_range<const _Vp>
3100 { return _Iterator<true>{ranges::end(_M_base)}; }
cba9ef06
PP
3101
3102 constexpr auto
3103 size() requires sized_range<_Vp>
3104 { return ranges::size(_M_base); }
3105
3106 constexpr auto
3107 size() const requires sized_range<const _Vp>
3108 { return ranges::size(_M_base); }
3109
3110 private:
97ab5daa
PP
3111 template<bool _Const>
3112 struct _Sentinel;
3113
cba9ef06
PP
3114 template<bool _Const>
3115 struct _Iterator
3116 {
8017d95c 3117 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
cba9ef06 3118
7433536b 3119 iterator_t<_Base> _M_current = iterator_t<_Base>();
cba9ef06
PP
3120
3121 friend _Iterator<!_Const>;
3122
3123 public:
3124 using iterator_category
3125 = typename iterator_traits<iterator_t<_Base>>::iterator_category;
3126 using value_type
3127 = remove_cvref_t<tuple_element_t<_Nm, range_value_t<_Base>>>;
3128 using difference_type = range_difference_t<_Base>;
3129
3130 _Iterator() = default;
3131
3132 constexpr explicit
3133 _Iterator(iterator_t<_Base> current)
3134 : _M_current(std::move(current))
3135 { }
3136
3137 constexpr
3138 _Iterator(_Iterator<!_Const> i)
3139 requires _Const && convertible_to<iterator_t<_Vp>, iterator_t<_Base>>
3140 : _M_current(std::move(i._M_current))
3141 { }
3142
3143 constexpr iterator_t<_Base>
3144 base() const&
3145 requires copyable<iterator_t<_Base>>
3146 { return _M_current; }
3147
3148 constexpr iterator_t<_Base>
3149 base() &&
3150 { return std::move(_M_current); }
3151
3152 constexpr decltype(auto)
3153 operator*() const
3154 { return std::get<_Nm>(*_M_current); }
3155
3156 constexpr _Iterator&
3157 operator++()
3158 {
3159 ++_M_current;
3160 return *this;
3161 }
3162
3163 constexpr void
3164 operator++(int) requires (!forward_range<_Base>)
3165 { ++_M_current; }
3166
3167 constexpr _Iterator
3168 operator++(int) requires forward_range<_Base>
3169 {
3170 auto __tmp = *this;
3171 ++_M_current;
3172 return __tmp;
3173 }
3174
3175 constexpr _Iterator&
3176 operator--() requires bidirectional_range<_Base>
3177 {
3178 --_M_current;
3179 return *this;
3180 }
3181
3182 constexpr _Iterator
3183 operator--(int) requires bidirectional_range<_Base>
3184 {
3185 auto __tmp = *this;
3186 --_M_current;
3187 return __tmp;
3188 }
3189
3190 constexpr _Iterator&
3191 operator+=(difference_type __n)
3192 requires random_access_range<_Base>
3193 {
3194 _M_current += __n;
3195 return *this;
3196 }
3197
3198 constexpr _Iterator&
3199 operator-=(difference_type __n)
3200 requires random_access_range<_Base>
3201 {
3202 _M_current -= __n;
3203 return *this;
3204 }
3205
3206 constexpr decltype(auto)
3207 operator[](difference_type __n) const
3208 requires random_access_range<_Base>
3209 { return std::get<_Nm>(*(_M_current + __n)); }
3210
3211 friend constexpr bool
3212 operator==(const _Iterator& __x, const _Iterator& __y)
3213 requires equality_comparable<iterator_t<_Base>>
3214 { return __x._M_current == __y._M_current; }
3215
cba9ef06
PP
3216 friend constexpr bool
3217 operator<(const _Iterator& __x, const _Iterator& __y)
3218 requires random_access_range<_Base>
3219 { return __x._M_current < __y._M_current; }
3220
3221 friend constexpr bool
3222 operator>(const _Iterator& __x, const _Iterator& __y)
3223 requires random_access_range<_Base>
3224 { return __y._M_current < __x._M_current; }
3225
3226 friend constexpr bool
3227 operator<=(const _Iterator& __x, const _Iterator& __y)
3228 requires random_access_range<_Base>
3229 { return !(__y._M_current > __x._M_current); }
3230
3231 friend constexpr bool
3232 operator>=(const _Iterator& __x, const _Iterator& __y)
3233 requires random_access_range<_Base>
3234 { return !(__x._M_current > __y._M_current); }
3235
3236#ifdef __cpp_lib_three_way_comparison
3237 friend constexpr auto
3238 operator<=>(const _Iterator& __x, const _Iterator& __y)
3239 requires random_access_range<_Base>
3240 && three_way_comparable<iterator_t<_Base>>
3241 { return __x._M_current <=> __y._M_current; }
3242#endif
3243
3244 friend constexpr _Iterator
3245 operator+(const _Iterator& __x, difference_type __y)
3246 requires random_access_range<_Base>
3247 { return _Iterator{__x} += __y; }
3248
3249 friend constexpr _Iterator
3250 operator+(difference_type __x, const _Iterator& __y)
3251 requires random_access_range<_Base>
3252 { return __y + __x; }
3253
3254 friend constexpr _Iterator
3255 operator-(const _Iterator& __x, difference_type __y)
3256 requires random_access_range<_Base>
3257 { return _Iterator{__x} -= __y; }
3258
2ec58cfc
JW
3259 // _GLIBCXX_RESOLVE_LIB_DEFECTS
3260 // 3483. transform_view::iterator's difference is overconstrained
cba9ef06
PP
3261 friend constexpr difference_type
3262 operator-(const _Iterator& __x, const _Iterator& __y)
2ec58cfc 3263 requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
cba9ef06
PP
3264 { return __x._M_current - __y._M_current; }
3265
97ab5daa
PP
3266 friend _Sentinel<_Const>;
3267 };
3268
3269 template<bool _Const>
3270 struct _Sentinel
3271 {
3272 private:
3273 constexpr bool
3274 _M_equal(const _Iterator<_Const>& __x) const
3275 { return __x._M_current == _M_end; }
3276
3277 using _Base = __detail::__maybe_const_t<_Const, _Vp>;
3278 sentinel_t<_Base> _M_end = sentinel_t<_Base>();
3279
3280 public:
3281 _Sentinel() = default;
3282
3283 constexpr explicit
3284 _Sentinel(sentinel_t<_Base> __end)
3285 : _M_end(std::move(__end))
3286 { }
3287
3288 constexpr
3289 _Sentinel(_Sentinel<!_Const> __other)
3290 requires _Const
3291 && convertible_to<sentinel_t<_Vp>, sentinel_t<_Base>>
3292 : _M_end(std::move(__other._M_end))
3293 { }
3294
3295 constexpr sentinel_t<_Base>
3296 base() const
3297 { return _M_end; }
3298
4be16d1c
PP
3299 template<bool _Const2>
3300 requires sentinel_for<sentinel_t<_Base>,
3301 iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>>
3302 friend constexpr bool
3303 operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y)
3304 { return __y._M_equal(__x); }
3305
3306 template<bool _Const2,
3307 typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
3308 requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
3309 friend constexpr range_difference_t<_Base2>
3310 operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y)
3311 { return __x._M_current - __y._M_end; }
3312
3313 template<bool _Const2,
3314 typename _Base2 = __detail::__maybe_const_t<_Const2, _Vp>>
3315 requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base2>>
3316 friend constexpr range_difference_t<_Base>
3317 operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y)
3318 { return __x._M_end - __y._M_current; }
97ab5daa
PP
3319
3320 friend _Sentinel<!_Const>;
cba9ef06
PP
3321 };
3322
3323 _Vp _M_base = _Vp();
3324 };
3325
39bf4f14
JW
3326 template<typename _Tp, size_t _Nm>
3327 inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Nm>>
3328 = enable_borrowed_range<_Tp>;
3329
cba9ef06 3330 template<typename _Range>
aca60ecf 3331 using keys_view = elements_view<views::all_t<_Range>, 0>;
cba9ef06
PP
3332
3333 template<typename _Range>
aca60ecf 3334 using values_view = elements_view<views::all_t<_Range>, 1>;
cba9ef06
PP
3335
3336 namespace views
3337 {
3338 template<size_t _Nm>
3339 inline constexpr __adaptor::_RangeAdaptorClosure elements
3340 = [] <viewable_range _Range> (_Range&& __r)
3341 {
aca60ecf
JW
3342 using _El = elements_view<views::all_t<_Range>, _Nm>;
3343 return _El{std::forward<_Range>(__r)};
cba9ef06
PP
3344 };
3345
3346 inline constexpr __adaptor::_RangeAdaptorClosure keys = elements<0>;
3347 inline constexpr __adaptor::_RangeAdaptorClosure values = elements<1>;
3348 } // namespace views
3349
3350} // namespace ranges
3351
3352 namespace views = ranges::views;
3353
328b52d6
JW
3354_GLIBCXX_END_NAMESPACE_VERSION
3355} // namespace
3356#endif // library concepts
3357#endif // C++2a
3358#endif /* _GLIBCXX_RANGES */