From Jason Turner

[range.adaptors]

Large diff (299.8 KB) - rendering may be slow on some devices

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp2xtfp9pe/{from.md → to.md} +6652 -624
tmp/tmp2xtfp9pe/{from.md → to.md} RENAMED
@@ -1,11 +1,13 @@
1
  ## Range adaptors <a id="range.adaptors">[[range.adaptors]]</a>
2
 
3
- This subclause defines *range adaptors*, which are utilities that
4
- transform a `range` into a `view` with custom behaviors. These adaptors
5
- can be chained to create pipelines of range transformations that
6
- evaluate lazily as the resulting view is iterated.
 
 
7
 
8
  Range adaptors are declared in namespace `std::ranges::views`.
9
 
10
  The bitwise operator is overloaded for the purpose of creating adaptor
11
  chain pipelines. The adaptors also support function call syntax with
@@ -16,123 +18,260 @@ equivalent semantics.
16
  ``` cpp
17
  vector<int> ints{0,1,2,3,4,5};
18
  auto even = [](int i) { return 0 == i % 2; };
19
  auto square = [](int i) { return i * i; };
20
  for (int i : ints | views::filter(even) | views::transform(square)) {
21
- cout << i << ' '; // prints: 0 4 16
22
  }
23
  assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
24
  ```
25
 
26
  — *end example*]
27
 
28
  ### Range adaptor objects <a id="range.adaptor.object">[[range.adaptor.object]]</a>
29
 
30
  A *range adaptor closure object* is a unary function object that accepts
31
- a `viewable_range` argument and returns a `view`. For a range adaptor
32
- closure object `C` and an expression `R` such that `decltype((R))`
33
- models `viewable_range`, the following expressions are equivalent and
34
- yield a `view`:
35
 
36
  ``` cpp
37
  C(R)
38
  R | C
39
  ```
40
 
41
  Given an additional range adaptor closure object `D`, the expression
42
- `C | D` is well-formed and produces another range adaptor closure object
43
- such that the following two expressions are equivalent:
 
44
 
45
- ``` cpp
46
- R | C | D
47
- R | (C | D)
48
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  A *range adaptor object* is a customization point object
51
  [[customization.point.object]] that accepts a `viewable_range` as its
52
- first argument and returns a `view`.
53
 
54
  If a range adaptor object accepts only one argument, then it is a range
55
  adaptor closure object.
56
 
57
- If a range adaptor object accepts more than one argument, then the
58
- following expressions are equivalent:
 
 
 
 
 
 
 
59
 
60
- ``` cpp
61
- adaptor(range, args...)
62
- adaptor(args...)(range)
63
- range | adaptor(args...)
64
- ```
 
65
 
66
- In this case, `adaptor(args...)` is a range adaptor closure object.
 
 
67
 
68
- ### Semiregular wrapper <a id="range.semi.wrap">[[range.semi.wrap]]</a>
69
 
70
  Many types in this subclause are specified in terms of an
71
- exposition-only class template *`semiregular-box`*. `semiregular-box<T>`
72
- behaves exactly like `optional<T>` with the following differences:
73
 
74
- - `semiregular-box<T>` constrains its type parameter `T` with
75
- `copy_constructible<T> && is_object_v<T>`.
76
- - If `T` models `default_initializable`, the default constructor of
77
- `semiregular-box<T>` is equivalent to:
78
  ``` cpp
79
- constexpr semiregular-box() noexcept(is_nothrow_default_constructible_v<T>)
80
- : semiregular-box{in_place}
81
- { }
82
  ```
83
- - If `assignable_from<T&, const T&>` is not modeled, the copy assignment
84
- operator is equivalent to:
85
  ``` cpp
86
- semiregular-box& operator=(const semiregular-box& that)
87
  noexcept(is_nothrow_copy_constructible_v<T>)
88
- {
 
89
  if (that) emplace(*that);
90
  else reset();
 
91
  return *this;
92
  }
93
  ```
94
- - If `assignable_from<T&, T>` is not modeled, the move assignment
95
- operator is equivalent to:
96
  ``` cpp
97
- semiregular-box& operator=(semiregular-box&& that)
98
- noexcept(is_nothrow_move_constructible_v<T>)
99
- {
100
  if (that) emplace(std::move(*that));
101
  else reset();
 
102
  return *this;
103
  }
104
  ```
105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  ### All view <a id="range.all">[[range.all]]</a>
107
 
108
- `views::all` returns a `view` that includes all elements of its `range`
 
 
109
  argument.
110
 
111
  The name `views::all` denotes a range adaptor object
112
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
113
  `views::all(E)` is expression-equivalent to:
114
 
115
  - `decay-copy(E)` if the decayed type of `E` models `view`.
116
  - Otherwise, `ref_view{E}` if that expression is well-formed.
117
- - Otherwise, `subrange{E}`.
118
 
119
  #### Class template `ref_view` <a id="range.ref.view">[[range.ref.view]]</a>
120
 
121
- `ref_view` is a `view` of the elements of some other `range`.
122
 
123
  ``` cpp
124
  namespace std::ranges {
125
  template<range R>
126
  requires is_object_v<R>
127
  class ref_view : public view_interface<ref_view<R>> {
128
  private:
129
- R* r_ = nullptr; // exposition only
130
- public:
131
- constexpr ref_view() noexcept = default;
132
 
133
- template<not-same-as<ref_view> T>
 
134
  requires see below
135
  constexpr ref_view(T&& t);
136
 
137
  constexpr R& base() const { return *r_; }
138
 
@@ -147,56 +286,194 @@ namespace std::ranges {
147
  { return ranges::size(*r_); }
148
 
149
  constexpr auto data() const requires contiguous_range<R>
150
  { return ranges::data(*r_); }
151
  };
 
152
  template<class R>
153
  ref_view(R&) -> ref_view<R>;
154
  }
155
  ```
156
 
157
  ``` cpp
158
- template<not-same-as<ref_view> T>
159
  requires see below
160
  constexpr ref_view(T&& t);
161
  ```
162
 
 
 
 
163
  *Remarks:* Let *`FUN`* denote the exposition-only functions
164
 
165
  ``` cpp
166
  void FUN(R&);
167
  void FUN(R&&) = delete;
168
  ```
169
 
170
- The expression in the *requires-clause* is equivalent to
171
 
172
  ``` cpp
173
  convertible_to<T, R&> && requires { FUN(declval<T>()); }
174
  ```
175
 
176
- *Effects:* Initializes *r\_* with
177
- `addressof(static_cast<R&>(std::forward<T>(t)))`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
  ### Filter view <a id="range.filter">[[range.filter]]</a>
180
 
181
  #### Overview <a id="range.filter.overview">[[range.filter.overview]]</a>
182
 
183
- `filter_view` presents a `view` of the elements of an underlying
184
- sequence that satisfy a predicate.
185
 
186
  The name `views::filter` denotes a range adaptor object
187
  [[range.adaptor.object]]. Given subexpressions `E` and `P`, the
188
  expression `views::filter(E, P)` is expression-equivalent to
189
- `filter_view{E, P}`.
190
 
191
  [*Example 1*:
192
 
193
  ``` cpp
194
  vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
195
- filter_view evens{is, [](int i) { return 0 == i % 2; }};
196
  for (int i : evens)
197
- cout << i << ' '; // prints: 0 2 4 6
198
  ```
199
 
200
  — *end example*]
201
 
202
  #### Class template `filter_view` <a id="range.filter.view">[[range.filter.view]]</a>
@@ -206,20 +483,21 @@ namespace std::ranges {
206
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
207
  requires view<V> && is_object_v<Pred>
208
  class filter_view : public view_interface<filter_view<V, Pred>> {
209
  private:
210
  V base_ = V(); // exposition only
211
- semiregular-box<Pred> pred_; // exposition only
212
 
213
  // [range.filter.iterator], class filter_view::iterator
214
  class iterator; // exposition only
 
215
  // [range.filter.sentinel], class filter_view::sentinel
216
  class sentinel; // exposition only
217
 
218
  public:
219
- filter_view() = default;
220
- constexpr filter_view(V base, Pred pred);
221
 
222
  constexpr V base() const & requires copy_constructible<V> { return base_; }
223
  constexpr V base() && { return std::move(base_); }
224
 
225
  constexpr const Pred& pred() const;
@@ -237,11 +515,11 @@ namespace std::ranges {
237
  filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
238
  }
239
  ```
240
 
241
  ``` cpp
242
- constexpr filter_view(V base, Pred pred);
243
  ```
244
 
245
  *Effects:* Initializes *base\_* with `std::move(base)` and initializes
246
  *pred\_* with `std::move(pred)`.
247
 
@@ -253,11 +531,11 @@ constexpr const Pred& pred() const;
253
 
254
  ``` cpp
255
  constexpr iterator begin();
256
  ```
257
 
258
- *Preconditions:* `pred_.has_value()`.
259
 
260
  *Returns:* `{*this, ranges::find_if(`*`base_`*`, ref(*`*`pred_`*`))}`.
261
 
262
  *Remarks:* In order to provide the amortized constant time complexity
263
  required by the `range` concept when `filter_view` models
@@ -272,21 +550,21 @@ namespace std::ranges {
272
  requires view<V> && is_object_v<Pred>
273
  class filter_view<V, Pred>::iterator {
274
  private:
275
  iterator_t<V> current_ = iterator_t<V>(); // exposition only
276
  filter_view* parent_ = nullptr; // exposition only
 
277
  public:
278
- using iterator_concept = see below;
279
- using iterator_category = see below;
280
  using value_type = range_value_t<V>;
281
  using difference_type = range_difference_t<V>;
282
 
283
- iterator() = default;
284
  constexpr iterator(filter_view& parent, iterator_t<V> current);
285
 
286
- constexpr iterator_t<V> base() const &
287
- requires copyable<iterator_t<V>>;
288
  constexpr iterator_t<V> base() &&;
289
  constexpr range_reference_t<V> operator*() const;
290
  constexpr iterator_t<V> operator->() const
291
  requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
292
 
@@ -300,10 +578,11 @@ namespace std::ranges {
300
  friend constexpr bool operator==(const iterator& x, const iterator& y)
301
  requires equality_comparable<iterator_t<V>>;
302
 
303
  friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
304
  noexcept(noexcept(ranges::iter_move(i.current_)));
 
305
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
306
  noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
307
  requires indirectly_swappable<iterator_t<V>>;
308
  };
309
  }
@@ -319,11 +598,13 @@ not satisfy the filter predicate.
319
  `bidirectional_iterator_tag`.
320
  - Otherwise, if `V` models `forward_range`, then `iterator_concept`
321
  denotes `forward_iterator_tag`.
322
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
323
 
324
- `iterator::iterator_category` is defined as follows:
 
 
325
 
326
  - Let `C` denote the type
327
  `iterator_traits<iterator_t<V>>::iterator_category`.
328
  - If `C` models `derived_from<bidirectional_iterator_tag>`, then
329
  `iterator_category` denotes `bidirectional_iterator_tag`.
@@ -337,21 +618,20 @@ constexpr iterator(filter_view& parent, iterator_t<V> current);
337
 
338
  *Effects:* Initializes *current\_* with `std::move(current)` and
339
  *parent\_* with `addressof(parent)`.
340
 
341
  ``` cpp
342
- constexpr iterator_t<V> base() const &
343
- requires copyable<iterator_t<V>>;
344
  ```
345
 
346
  *Effects:* Equivalent to: `return `*`current_`*`;`
347
 
348
  ``` cpp
349
  constexpr iterator_t<V> base() &&;
350
  ```
351
 
352
- *Effects:* Equivalent to: `return std::move(current_);`
353
 
354
  ``` cpp
355
  constexpr range_reference_t<V> operator*() const;
356
  ```
357
 
@@ -449,10 +729,11 @@ namespace std::ranges {
449
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
450
  requires view<V> && is_object_v<Pred>
451
  class filter_view<V, Pred>::sentinel {
452
  private:
453
  sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
 
454
  public:
455
  sentinel() = default;
456
  constexpr explicit sentinel(filter_view& parent);
457
 
458
  constexpr sentinel_t<V> base() const;
@@ -482,50 +763,51 @@ friend constexpr bool operator==(const iterator& x, const sentinel& y);
482
 
483
  ### Transform view <a id="range.transform">[[range.transform]]</a>
484
 
485
  #### Overview <a id="range.transform.overview">[[range.transform.overview]]</a>
486
 
487
- `transform_view` presents a `view` of an underlying sequence after
488
  applying a transformation function to each element.
489
 
490
  The name `views::transform` denotes a range adaptor object
491
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
492
  expression `views::transform(E, F)` is expression-equivalent to
493
- `transform_view{E, F}`.
494
 
495
  [*Example 1*:
496
 
497
  ``` cpp
498
  vector<int> is{ 0, 1, 2, 3, 4 };
499
- transform_view squares{is, [](int i) { return i * i; }};
500
  for (int i : squares)
501
- cout << i << ' '; // prints: 0 1 4 9 16
502
  ```
503
 
504
  — *end example*]
505
 
506
  #### Class template `transform_view` <a id="range.transform.view">[[range.transform.view]]</a>
507
 
508
  ``` cpp
509
  namespace std::ranges {
510
- template<input_range V, copy_constructible F>
511
  requires view<V> && is_object_v<F> &&
512
  regular_invocable<F&, range_reference_t<V>> &&
513
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
514
  class transform_view : public view_interface<transform_view<V, F>> {
515
  private:
516
  // [range.transform.iterator], class template transform_view::iterator
517
  template<bool> struct iterator; // exposition only
 
518
  // [range.transform.sentinel], class template transform_view::sentinel
519
  template<bool> struct sentinel; // exposition only
520
 
521
  V base_ = V(); // exposition only
522
- semiregular-box<F> fun_; // exposition only
523
 
524
  public:
525
- transform_view() = default;
526
- constexpr transform_view(V base, F fun);
527
 
528
  constexpr V base() const & requires copy_constructible<V> { return base_; }
529
  constexpr V base() && { return std::move(base_); }
530
 
531
  constexpr iterator<false> begin();
@@ -551,11 +833,11 @@ namespace std::ranges {
551
  transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
552
  }
553
  ```
554
 
555
  ``` cpp
556
- constexpr transform_view(V base, F fun);
557
  ```
558
 
559
  *Effects:* Initializes *base\_* with `std::move(base)` and *fun\_* with
560
  `std::move(fun)`.
561
 
@@ -627,41 +909,41 @@ return iterator<true>{*this, ranges::end(base_)};
627
 
628
  #### Class template `transform_view::iterator` <a id="range.transform.iterator">[[range.transform.iterator]]</a>
629
 
630
  ``` cpp
631
  namespace std::ranges {
632
- template<input_range V, copy_constructible F>
633
  requires view<V> && is_object_v<F> &&
634
  regular_invocable<F&, range_reference_t<V>> &&
635
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
636
  template<bool Const>
637
  class transform_view<V, F>::iterator {
638
  private:
639
- using Parent = // exposition only
640
- conditional_t<Const, const transform_view, transform_view>;
641
- using Base = // exposition only
642
- conditional_t<Const, const V, V>;
643
- iterator_t<Base> current_ = // exposition only
644
- iterator_t<Base>();
645
  Parent* parent_ = nullptr; // exposition only
 
646
  public:
647
- using iterator_concept = see below;
648
- using iterator_category = see below;
649
  using value_type =
650
- remove_cvref_t<invoke_result_t<F&, range_reference_t<Base>>>;
651
  using difference_type = range_difference_t<Base>;
652
 
653
- iterator() = default;
654
  constexpr iterator(Parent& parent, iterator_t<Base> current);
655
  constexpr iterator(iterator<!Const> i)
656
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
657
 
658
- constexpr iterator_t<Base> base() const &
659
- requires copyable<iterator_t<Base>>;
660
  constexpr iterator_t<Base> base() &&;
 
661
  constexpr decltype(auto) operator*() const
662
- { return invoke(*parent_->fun_, *current_); }
 
 
663
 
664
  constexpr iterator& operator++();
665
  constexpr void operator++(int);
666
  constexpr iterator operator++(int) requires forward_range<Base>;
667
 
@@ -670,13 +952,15 @@ namespace std::ranges {
670
 
671
  constexpr iterator& operator+=(difference_type n)
672
  requires random_access_range<Base>;
673
  constexpr iterator& operator-=(difference_type n)
674
  requires random_access_range<Base>;
 
675
  constexpr decltype(auto) operator[](difference_type n) const
676
- requires random_access_range<Base>
677
- { return invoke(*parent_->fun_, current_[n]); }
 
678
 
679
  friend constexpr bool operator==(const iterator& x, const iterator& y)
680
  requires equality_comparable<iterator_t<Base>>;
681
 
682
  friend constexpr bool operator<(const iterator& x, const iterator& y)
@@ -696,43 +980,32 @@ namespace std::ranges {
696
  requires random_access_range<Base>;
697
 
698
  friend constexpr iterator operator-(iterator i, difference_type n)
699
  requires random_access_range<Base>;
700
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
701
- requires random_access_range<Base>;
702
-
703
- friend constexpr decltype(auto) iter_move(const iterator& i)
704
- noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
705
- {
706
- if constexpr (is_lvalue_reference_v<decltype(*i)>)
707
- return std::move(*i);
708
- else
709
- return *i;
710
- }
711
-
712
- friend constexpr void iter_swap(const iterator& x, const iterator& y)
713
- noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
714
- requires indirectly_swappable<iterator_t<Base>>;
715
  };
716
  }
717
  ```
718
 
719
  `iterator::iterator_concept` is defined as follows:
720
 
721
- - If `V` models `random_access_range`, then `iterator_concept` denotes
722
- `random_access_iterator_tag`.
723
- - Otherwise, if `V` models `bidirectional_range`, then
724
  `iterator_concept` denotes `bidirectional_iterator_tag`.
725
- - Otherwise, if `V` models `forward_range`, then `iterator_concept`
726
  denotes `forward_iterator_tag`.
727
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
728
 
 
 
729
  `iterator::iterator_category` is defined as follows: Let `C` denote the
730
  type `iterator_traits<iterator_t<Base>>::iterator_category`.
731
 
732
  - If
733
- `is_lvalue_reference_v<invoke_result_t<F&, range_reference_t<Base>>>`
734
  is `true`, then
735
  - if `C` models `derived_from<contiguous_iterator_tag>`,
736
  `iterator_category` denotes `random_access_iterator_tag`;
737
  - otherwise, `iterator_category` denotes `C`.
738
  - Otherwise, `iterator_category` denotes `input_iterator_tag`.
@@ -751,21 +1024,20 @@ constexpr iterator(iterator<!Const> i)
751
 
752
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
753
  and *parent\_* with `i.`*`parent_`*.
754
 
755
  ``` cpp
756
- constexpr iterator_t<Base> base() const &
757
- requires copyable<iterator_t<Base>>;
758
  ```
759
 
760
  *Effects:* Equivalent to: `return `*`current_`*`;`
761
 
762
  ``` cpp
763
  constexpr iterator_t<Base> base() &&;
764
  ```
765
 
766
- *Effects:* Equivalent to: `return std::move(current_);`
767
 
768
  ``` cpp
769
  constexpr iterator& operator++();
770
  ```
771
 
@@ -778,11 +1050,11 @@ return *this;
778
 
779
  ``` cpp
780
  constexpr void operator++(int);
781
  ```
782
 
783
- *Effects:* Equivalent to `++current_`.
784
 
785
  ``` cpp
786
  constexpr iterator operator++(int) requires forward_range<Base>;
787
  ```
788
 
@@ -890,67 +1162,63 @@ friend constexpr iterator operator+(iterator i, difference_type n)
890
  friend constexpr iterator operator+(difference_type n, iterator i)
891
  requires random_access_range<Base>;
892
  ```
893
 
894
  *Effects:* Equivalent to:
895
- `return iterator{*i.`*`parent_`*`, i.`*`current_`*` + n};`
896
 
897
  ``` cpp
898
  friend constexpr iterator operator-(iterator i, difference_type n)
899
  requires random_access_range<Base>;
900
  ```
901
 
902
  *Effects:* Equivalent to:
903
- `return iterator{*i.`*`parent_`*`, i.`*`current_`*` - n};`
904
 
905
  ``` cpp
906
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
907
- requires random_access_range<Base>;
908
  ```
909
 
910
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
911
 
912
- ``` cpp
913
- friend constexpr void iter_swap(const iterator& x, const iterator& y)
914
- noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
915
- requires indirectly_swappable<iterator_t<Base>>;
916
- ```
917
-
918
- *Effects:* Equivalent to
919
- `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
920
-
921
  #### Class template `transform_view::sentinel` <a id="range.transform.sentinel">[[range.transform.sentinel]]</a>
922
 
923
  ``` cpp
924
  namespace std::ranges {
925
- template<input_range V, copy_constructible F>
926
  requires view<V> && is_object_v<F> &&
927
  regular_invocable<F&, range_reference_t<V>> &&
928
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
929
  template<bool Const>
930
  class transform_view<V, F>::sentinel {
931
  private:
932
- using Parent = // exposition only
933
- conditional_t<Const, const transform_view, transform_view>;
934
- using Base = conditional_t<Const, const V, V>; // exposition only
935
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
936
  public:
937
  sentinel() = default;
938
  constexpr explicit sentinel(sentinel_t<Base> end);
939
  constexpr sentinel(sentinel<!Const> i)
940
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
941
 
942
  constexpr sentinel_t<Base> base() const;
943
 
944
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
945
 
946
- friend constexpr range_difference_t<Base>
947
- operator-(const iterator<Const>& x, const sentinel& y)
948
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
949
- friend constexpr range_difference_t<Base>
950
- operator-(const sentinel& y, const iterator<Const>& x)
951
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
 
 
952
  };
953
  }
954
  ```
955
 
956
  ``` cpp
@@ -971,67 +1239,86 @@ constexpr sentinel_t<Base> base() const;
971
  ```
972
 
973
  *Effects:* Equivalent to: `return `*`end_`*`;`
974
 
975
  ``` cpp
976
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
977
  ```
978
 
979
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
980
 
981
  ``` cpp
982
- friend constexpr range_difference_t<Base>
983
- operator-(const iterator<Const>& x, const sentinel& y)
984
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
985
  ```
986
 
987
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
988
 
989
  ``` cpp
990
- friend constexpr range_difference_t<Base>
991
- operator-(const sentinel& y, const iterator<Const>& x)
992
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
993
  ```
994
 
995
  *Effects:* Equivalent to: `return y.`*`end_`*` - x.`*`current_`*`;`
996
 
997
  ### Take view <a id="range.take">[[range.take]]</a>
998
 
999
  #### Overview <a id="range.take.overview">[[range.take.overview]]</a>
1000
 
1001
- `take_view` produces a `view` of the first N elements from another
1002
- `view`, or all the elements if the adapted `view` contains fewer than N.
1003
 
1004
  The name `views::take` denotes a range adaptor object
1005
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
1006
  `remove_cvref_t<decltype((E))>`, and let `D` be
1007
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
1008
  `convertible_to<D>`, `views::take(E, F)` is ill-formed. Otherwise, the
1009
  expression `views::take(E, F)` is expression-equivalent to:
1010
 
1011
- - If `T` is a specialization of `ranges::empty_view`
1012
- [[range.empty.view]], then `((void) F, decay-copy(E))`.
 
1013
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
1014
- is
1015
- - a specialization of `span` [[views.span]] where
1016
- `T::extent == dynamic_extent`,
1017
- - a specialization of `basic_string_view` [[string.view]],
1018
- - a specialization of `ranges::iota_view` [[range.iota.view]], or
1019
- - a specialization of `ranges::subrange` [[range.subrange]],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1020
 
1021
- then
1022
- `T{ranges::begin(E), ranges::begin(E) + min<D>(ranges::size(E), F)}`,
1023
- except that `E` is evaluated only once.
1024
- - Otherwise, `ranges::take_view{E, F}`.
1025
 
1026
  [*Example 1*:
1027
 
1028
  ``` cpp
1029
  vector<int> is{0,1,2,3,4,5,6,7,8,9};
1030
- take_view few{is, 5};
1031
- for (int i : few)
1032
- cout << i << ' '; // prints: 0 1 2 3 4
1033
  ```
1034
 
1035
  — *end example*]
1036
 
1037
  #### Class template `take_view` <a id="range.take.view">[[range.take.view]]</a>
@@ -1041,62 +1328,80 @@ namespace std::ranges {
1041
  template<view V>
1042
  class take_view : public view_interface<take_view<V>> {
1043
  private:
1044
  V base_ = V(); // exposition only
1045
  range_difference_t<V> count_ = 0; // exposition only
 
1046
  // [range.take.sentinel], class template take_view::sentinel
1047
- template<bool> struct sentinel; // exposition only
 
1048
  public:
1049
- take_view() = default;
1050
- constexpr take_view(V base, range_difference_t<V> count);
1051
 
1052
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1053
  constexpr V base() && { return std::move(base_); }
1054
 
1055
  constexpr auto begin() requires (!simple-view<V>) {
1056
  if constexpr (sized_range<V>) {
1057
- if constexpr (random_access_range<V>)
1058
  return ranges::begin(base_);
1059
- else {
1060
- auto sz = size();
1061
- return counted_iterator{ranges::begin(base_), sz};
 
 
 
 
 
 
 
1062
  }
1063
- } else
1064
- return counted_iterator{ranges::begin(base_), count_};
1065
  }
1066
 
1067
  constexpr auto begin() const requires range<const V> {
1068
  if constexpr (sized_range<const V>) {
1069
- if constexpr (random_access_range<const V>)
1070
  return ranges::begin(base_);
1071
- else {
1072
- auto sz = size();
1073
- return counted_iterator{ranges::begin(base_), sz};
 
 
 
 
 
 
 
1074
  }
1075
- } else
1076
- return counted_iterator{ranges::begin(base_), count_};
1077
  }
1078
 
1079
  constexpr auto end() requires (!simple-view<V>) {
1080
  if constexpr (sized_range<V>) {
1081
  if constexpr (random_access_range<V>)
1082
- return ranges::begin(base_) + size();
1083
  else
1084
  return default_sentinel;
1085
- } else
 
 
1086
  return sentinel<false>{ranges::end(base_)};
1087
  }
 
1088
 
1089
  constexpr auto end() const requires range<const V> {
1090
  if constexpr (sized_range<const V>) {
1091
  if constexpr (random_access_range<const V>)
1092
- return ranges::begin(base_) + size();
1093
  else
1094
  return default_sentinel;
1095
- } else
 
 
1096
  return sentinel<true>{ranges::end(base_)};
1097
  }
 
1098
 
1099
  constexpr auto size() requires sized_range<V> {
1100
  auto n = ranges::size(base_);
1101
  return ranges::min(n, static_cast<decltype(n)>(count_));
1102
  }
@@ -1105,20 +1410,22 @@ namespace std::ranges {
1105
  auto n = ranges::size(base_);
1106
  return ranges::min(n, static_cast<decltype(n)>(count_));
1107
  }
1108
  };
1109
 
1110
- template<range R>
1111
  take_view(R&&, range_difference_t<R>)
1112
  -> take_view<views::all_t<R>>;
1113
  }
1114
  ```
1115
 
1116
  ``` cpp
1117
- constexpr take_view(V base, range_difference_t<V> count);
1118
  ```
1119
 
 
 
1120
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
1121
  with `count`.
1122
 
1123
  #### Class template `take_view::sentinel` <a id="range.take.sentinel">[[range.take.sentinel]]</a>
1124
 
@@ -1126,22 +1433,28 @@ with `count`.
1126
  namespace std::ranges {
1127
  template<view V>
1128
  template<bool Const>
1129
  class take_view<V>::sentinel {
1130
  private:
1131
- using Base = conditional_t<Const, const V, V>; // exposition only
1132
- using CI = counted_iterator<iterator_t<Base>>; // exposition only
 
1133
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
1134
  public:
1135
  sentinel() = default;
1136
  constexpr explicit sentinel(sentinel_t<Base> end);
1137
  constexpr sentinel(sentinel<!Const> s)
1138
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1139
 
1140
  constexpr sentinel_t<Base> base() const;
1141
 
1142
- friend constexpr bool operator==(const CI& y, const sentinel& x);
 
 
 
 
1143
  };
1144
  }
1145
  ```
1146
 
1147
  ``` cpp
@@ -1162,35 +1475,39 @@ constexpr sentinel_t<Base> base() const;
1162
  ```
1163
 
1164
  *Effects:* Equivalent to: `return `*`end_`*`;`
1165
 
1166
  ``` cpp
1167
- friend constexpr bool operator==(const CI& y, const sentinel& x);
 
 
 
 
1168
  ```
1169
 
1170
  *Effects:* Equivalent to:
1171
  `return y.count() == 0 || y.base() == x.`*`end_`*`;`
1172
 
1173
  ### Take while view <a id="range.take.while">[[range.take.while]]</a>
1174
 
1175
  #### Overview <a id="range.take.while.overview">[[range.take.while.overview]]</a>
1176
 
1177
- Given a unary predicate `pred` and a `view` `r`, `take_while_view`
1178
- produces a `view` of the range \[`begin(r)`,
1179
  `ranges::find_if_not(r, pred)`).
1180
 
1181
  The name `views::take_while` denotes a range adaptor object
1182
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1183
  expression `views::take_while(E, F)` is expression-equivalent to
1184
- `take_while_view{E, F}`.
1185
 
1186
  [*Example 1*:
1187
 
1188
  ``` cpp
1189
  auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
1190
  auto small = [](const auto x) noexcept { return x < 5; };
1191
- auto small_ints = istream_view<int>(input) | views::take_while(small);
1192
  for (const auto i : small_ints) {
1193
  cout << i << ' '; // prints 0 1 2 3 4
1194
  }
1195
  auto i = 0;
1196
  input >> i;
@@ -1209,41 +1526,45 @@ namespace std::ranges {
1209
  class take_while_view : public view_interface<take_while_view<V, Pred>> {
1210
  // [range.take.while.sentinel], class template take_while_view::sentinel
1211
  template<bool> class sentinel; // exposition only
1212
 
1213
  V base_ = V(); // exposition only
1214
- semiregular-box<Pred> pred_; // exposition only
1215
 
1216
  public:
1217
- take_while_view() = default;
1218
- constexpr take_while_view(V base, Pred pred);
1219
 
1220
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1221
  constexpr V base() && { return std::move(base_); }
1222
 
1223
  constexpr const Pred& pred() const;
1224
 
1225
  constexpr auto begin() requires (!simple-view<V>)
1226
  { return ranges::begin(base_); }
1227
 
1228
- constexpr auto begin() const requires range<const V>
 
 
1229
  { return ranges::begin(base_); }
1230
 
1231
  constexpr auto end() requires (!simple-view<V>)
1232
  { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
1233
 
1234
- constexpr auto end() const requires range<const V>
 
 
1235
  { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
1236
  };
1237
 
1238
  template<class R, class Pred>
1239
  take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
1240
  }
1241
  ```
1242
 
1243
  ``` cpp
1244
- constexpr take_while_view(V base, Pred pred);
1245
  ```
1246
 
1247
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
1248
  `std::move(pred)`.
1249
 
@@ -1259,24 +1580,30 @@ constexpr const Pred& pred() const;
1259
  namespace std::ranges {
1260
  template<view V, class Pred>
1261
  requires input_range<V> && is_object_v<Pred> &&
1262
  indirect_unary_predicate<const Pred, iterator_t<V>>
1263
  template<bool Const>
1264
- class take_while_view<V, Pred>::sentinel { // exposition only
1265
- using Base = conditional_t<Const, const V, V>; // exposition only
1266
 
1267
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1268
  const Pred* pred_ = nullptr; // exposition only
 
1269
  public:
1270
  sentinel() = default;
1271
  constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
1272
  constexpr sentinel(sentinel<!Const> s)
1273
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1274
 
1275
  constexpr sentinel_t<Base> base() const { return end_; }
1276
 
1277
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
 
 
 
 
 
1278
  };
1279
  }
1280
  ```
1281
 
1282
  ``` cpp
@@ -1288,56 +1615,79 @@ constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
1288
  ``` cpp
1289
  constexpr sentinel(sentinel<!Const> s)
1290
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1291
  ```
1292
 
1293
- *Effects:* Initializes *end\_* with `s.`*`end_`* and *pred\_* with
1294
- `s.`*`pred_`*.
1295
 
1296
  ``` cpp
1297
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
 
 
 
 
 
1298
  ```
1299
 
1300
  *Effects:* Equivalent to:
1301
  `return y.`*`end_`*` == x || !invoke(*y.`*`pred_`*`, *x);`
1302
 
1303
  ### Drop view <a id="range.drop">[[range.drop]]</a>
1304
 
1305
  #### Overview <a id="range.drop.overview">[[range.drop.overview]]</a>
1306
 
1307
- `drop_view` produces a `view` excluding the first N elements from
1308
- another `view`, or an empty range if the adapted `view` contains fewer
1309
- than N elements.
1310
 
1311
  The name `views::drop` denotes a range adaptor object
1312
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
1313
  `remove_cvref_t<decltype((E))>`, and let `D` be
1314
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
1315
  `convertible_to<D>`, `views::drop(E, F)` is ill-formed. Otherwise, the
1316
  expression `views::drop(E, F)` is expression-equivalent to:
1317
 
1318
- - If `T` is a specialization of `ranges::empty_view`
1319
- [[range.empty.view]], then `((void) F, decay-copy(E))`.
 
1320
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
1321
  is
1322
- - a specialization of `span` [[views.span]] where
1323
- `T::extent == dynamic_extent`,
1324
  - a specialization of `basic_string_view` [[string.view]],
1325
- - a specialization of `ranges::iota_view` [[range.iota.view]], or
1326
- - a specialization of `ranges::subrange` [[range.subrange]],
 
1327
 
1328
  then
1329
- `T{ranges::begin(E) + min<D>(ranges::size(E), F), ranges::end(E)}`,
1330
- except that `E` is evaluated only once.
1331
- - Otherwise, `ranges::drop_view{E, F}`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1332
 
1333
  [*Example 1*:
1334
 
1335
  ``` cpp
1336
  auto ints = views::iota(0) | views::take(10);
1337
- auto latter_half = drop_view{ints, 5};
1338
- for (auto i : latter_half) {
1339
  cout << i << ' '; // prints 5 6 7 8 9
1340
  }
1341
  ```
1342
 
1343
  — *end example*]
@@ -1347,44 +1697,40 @@ for (auto i : latter_half) {
1347
  ``` cpp
1348
  namespace std::ranges {
1349
  template<view V>
1350
  class drop_view : public view_interface<drop_view<V>> {
1351
  public:
1352
- drop_view() = default;
1353
- constexpr drop_view(V base, range_difference_t<V> count);
1354
 
1355
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1356
  constexpr V base() && { return std::move(base_); }
1357
 
1358
  constexpr auto begin()
1359
- requires (!(simple-view<V> && random_access_range<V>));
 
1360
  constexpr auto begin() const
1361
- requires random_access_range<const V>;
1362
 
1363
- constexpr auto end()
1364
- requires (!simple-view<V>)
1365
  { return ranges::end(base_); }
1366
 
1367
- constexpr auto end() const
1368
- requires range<const V>
1369
  { return ranges::end(base_); }
1370
 
1371
- constexpr auto size()
1372
- requires sized_range<V>
1373
- {
1374
  const auto s = ranges::size(base_);
1375
  const auto c = static_cast<decltype(s)>(count_);
1376
  return s < c ? 0 : s - c;
1377
  }
1378
 
1379
- constexpr auto size() const
1380
- requires sized_range<const V>
1381
- {
1382
  const auto s = ranges::size(base_);
1383
  const auto c = static_cast<decltype(s)>(count_);
1384
  return s < c ? 0 : s - c;
1385
  }
 
1386
  private:
1387
  V base_ = V(); // exposition only
1388
  range_difference_t<V> count_ = 0; // exposition only
1389
  };
1390
 
@@ -1392,27 +1738,28 @@ namespace std::ranges {
1392
  drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
1393
  }
1394
  ```
1395
 
1396
  ``` cpp
1397
- constexpr drop_view(V base, range_difference_t<V> count);
1398
  ```
1399
 
1400
  *Preconditions:* `count >= 0` is `true`.
1401
 
1402
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
1403
  with `count`.
1404
 
1405
  ``` cpp
1406
  constexpr auto begin()
1407
- requires (!(simple-view<V> && random_access_range<V>));
 
1408
  constexpr auto begin() const
1409
- requires random_access_range<const V>;
1410
  ```
1411
 
1412
  *Returns:*
1413
- `ranges::next(ranges::begin(base_), count_, ranges::end(base_))`.
1414
 
1415
  *Remarks:* In order to provide the amortized constant-time complexity
1416
  required by the `range` concept when `drop_view` models `forward_range`,
1417
  the first overload caches the result within the `drop_view` for use on
1418
  subsequent calls.
@@ -1422,25 +1769,25 @@ would have quadratic iteration complexity. — *end note*]
1422
 
1423
  ### Drop while view <a id="range.drop.while">[[range.drop.while]]</a>
1424
 
1425
  #### Overview <a id="range.drop.while.overview">[[range.drop.while.overview]]</a>
1426
 
1427
- Given a unary predicate `pred` and a `view` `r`, `drop_while_view`
1428
- produces a `view` of the range \[`ranges::find_if_not(r, pred)`,
1429
  `ranges::end(r)`).
1430
 
1431
  The name `views::drop_while` denotes a range adaptor object
1432
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1433
  expression `views::drop_while(E, F)` is expression-equivalent to
1434
- `drop_while_view{E, F}`.
1435
 
1436
  [*Example 1*:
1437
 
1438
  ``` cpp
1439
- constexpr auto source = " \t \t \t hello there";
1440
  auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
1441
- auto skip_ws = drop_while_view{source, is_invisible};
1442
  for (auto c : skip_ws) {
1443
  cout << c; // prints hello there with no leading space
1444
  }
1445
  ```
1446
 
@@ -1453,35 +1800,34 @@ namespace std::ranges {
1453
  template<view V, class Pred>
1454
  requires input_range<V> && is_object_v<Pred> &&
1455
  indirect_unary_predicate<const Pred, iterator_t<V>>
1456
  class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
1457
  public:
1458
- drop_while_view() = default;
1459
- constexpr drop_while_view(V base, Pred pred);
1460
 
1461
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1462
  constexpr V base() && { return std::move(base_); }
1463
 
1464
  constexpr const Pred& pred() const;
1465
 
1466
  constexpr auto begin();
1467
 
1468
- constexpr auto end()
1469
- { return ranges::end(base_); }
1470
 
1471
  private:
1472
  V base_ = V(); // exposition only
1473
- semiregular-box<Pred> pred_; // exposition only
1474
  };
1475
 
1476
  template<class R, class Pred>
1477
  drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
1478
  }
1479
  ```
1480
 
1481
  ``` cpp
1482
- constexpr drop_while_view(V base, Pred pred);
1483
  ```
1484
 
1485
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
1486
  `std::move(pred)`.
1487
 
@@ -1493,11 +1839,13 @@ constexpr const Pred& pred() const;
1493
 
1494
  ``` cpp
1495
  constexpr auto begin();
1496
  ```
1497
 
1498
- *Returns:* `ranges::find_if_not(base_, cref(*pred_))`.
 
 
1499
 
1500
  *Remarks:* In order to provide the amortized constant-time complexity
1501
  required by the `range` concept when `drop_while_view` models
1502
  `forward_range`, the first call caches the result within the
1503
  `drop_while_view` for use on subsequent calls.
@@ -1508,67 +1856,75 @@ complexity. — *end note*]
1508
 
1509
  ### Join view <a id="range.join">[[range.join]]</a>
1510
 
1511
  #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
1512
 
1513
- `join_view` flattens a `view` of ranges into a `view`.
1514
 
1515
  The name `views::join` denotes a range adaptor object
1516
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
1517
- `views::join(E)` is expression-equivalent to `join_view{E}`.
 
1518
 
1519
  [*Example 1*:
1520
 
1521
  ``` cpp
1522
  vector<string> ss{"hello", " ", "world", "!"};
1523
- join_view greeting{ss};
1524
- for (char ch : greeting)
1525
- cout << ch; // prints: hello world!
1526
  ```
1527
 
1528
  — *end example*]
1529
 
1530
  #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
1531
 
1532
  ``` cpp
1533
  namespace std::ranges {
1534
  template<input_range V>
1535
- requires view<V> && input_range<range_reference_t<V>> &&
1536
- (is_reference_v<range_reference_t<V>> ||
1537
- view<range_value_t<V>>)
1538
  class join_view : public view_interface<join_view<V>> {
1539
  private:
1540
- using InnerRng = // exposition only
1541
- range_reference_t<V>;
1542
  // [range.join.iterator], class template join_view::iterator
1543
  template<bool Const>
1544
  struct iterator; // exposition only
 
1545
  // [range.join.sentinel], class template join_view::sentinel
1546
  template<bool Const>
1547
  struct sentinel; // exposition only
1548
 
1549
  V base_ = V(); // exposition only
1550
- views::all_t<InnerRng> inner_ = // exposition only, present only when !is_reference_v<InnerRng>
1551
- views::all_t<InnerRng>();
 
 
 
 
1552
  public:
1553
- join_view() = default;
1554
  constexpr explicit join_view(V base);
1555
 
1556
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1557
  constexpr V base() && { return std::move(base_); }
1558
 
1559
  constexpr auto begin() {
 
1560
  constexpr bool use_const = simple-view<V> &&
1561
- is_reference_v<range_reference_t<V>>;
1562
  return iterator<use_const>{*this, ranges::begin(base_)};
 
 
 
 
1563
  }
1564
 
1565
  constexpr auto begin() const
1566
- requires input_range<const V> &&
1567
- is_reference_v<range_reference_t<const V>> {
1568
- return iterator<true>{*this, ranges::begin(base_)};
1569
- }
1570
 
1571
  constexpr auto end() {
1572
  if constexpr (forward_range<V> &&
1573
  is_reference_v<InnerRng> && forward_range<InnerRng> &&
1574
  common_range<V> && common_range<InnerRng>)
@@ -1576,15 +1932,14 @@ namespace std::ranges {
1576
  else
1577
  return sentinel<simple-view<V>>{*this};
1578
  }
1579
 
1580
  constexpr auto end() const
1581
- requires input_range<const V> &&
1582
- is_reference_v<range_reference_t<const V>> {
1583
- if constexpr (forward_range<const V> &&
1584
  is_reference_v<range_reference_t<const V>> &&
1585
- forward_range<range_reference_t<const V>> &&
 
1586
  common_range<const V> &&
1587
  common_range<range_reference_t<const V>>)
1588
  return iterator<true>{*this, ranges::end(base_)};
1589
  else
1590
  return sentinel<true>{*this};
@@ -1605,47 +1960,53 @@ constexpr explicit join_view(V base);
1605
  #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
1606
 
1607
  ``` cpp
1608
  namespace std::ranges {
1609
  template<input_range V>
1610
- requires view<V> && input_range<range_reference_t<V>> &&
1611
- (is_reference_v<range_reference_t<V>> ||
1612
- view<range_value_t<V>>)
1613
  template<bool Const>
1614
  struct join_view<V>::iterator {
1615
  private:
1616
- using Parent = // exposition only
1617
- conditional_t<Const, const join_view, join_view>;
1618
- using Base = conditional_t<Const, const V, V>; // exposition only
 
1619
 
1620
  static constexpr bool ref-is-glvalue = // exposition only
1621
  is_reference_v<range_reference_t<Base>>;
1622
 
1623
- iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only
1624
- iterator_t<range_reference_t<Base>> inner_ = // exposition only
1625
- iterator_t<range_reference_t<Base>>();
1626
  Parent* parent_ = nullptr; // exposition only
1627
 
1628
  constexpr void satisfy(); // exposition only
 
 
 
 
 
 
 
 
 
1629
  public:
1630
  using iterator_concept = see below;
1631
- using iterator_category = see below;
1632
  using value_type = range_value_t<range_reference_t<Base>>;
1633
  using difference_type = see below;
1634
 
1635
  iterator() = default;
1636
- constexpr iterator(Parent& parent, iterator_t<Base> outer);
1637
  constexpr iterator(iterator<!Const> i)
1638
  requires Const &&
1639
- convertible_to<iterator_t<V>, iterator_t<Base>> &&
1640
- convertible_to<iterator_t<InnerRng>,
1641
- iterator_t<range_reference_t<Base>>>;
1642
 
1643
- constexpr decltype(auto) operator*() const { return *inner_; }
1644
 
1645
- constexpr iterator_t<Base> operator->() const
1646
- requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
1647
 
1648
  constexpr iterator& operator++();
1649
  constexpr void operator++(int);
1650
  constexpr iterator operator++(int)
1651
  requires ref-is-glvalue && forward_range<Base> &&
@@ -1660,50 +2021,53 @@ namespace std::ranges {
1660
  requires ref-is-glvalue && bidirectional_range<Base> &&
1661
  bidirectional_range<range_reference_t<Base>> &&
1662
  common_range<range_reference_t<Base>>;
1663
 
1664
  friend constexpr bool operator==(const iterator& x, const iterator& y)
1665
- requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
1666
  equality_comparable<iterator_t<range_reference_t<Base>>>;
1667
 
1668
  friend constexpr decltype(auto) iter_move(const iterator& i)
1669
- noexcept(noexcept(ranges::iter_move(i.inner_))) {
1670
- return ranges::iter_move(i.inner_);
1671
  }
1672
 
1673
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
1674
- noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
 
1675
  };
1676
  }
1677
  ```
1678
 
1679
  `iterator::iterator_concept` is defined as follows:
1680
 
1681
- - If *`ref-is-glvalue`* is `true` and *`Base`* and
1682
- `range_reference_t<Base>` each model `bidirectional_range`, then
1683
- `iterator_concept` denotes `bidirectional_iterator_tag`.
 
1684
  - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
1685
  `range_reference_t<Base>` each model , then `iterator_concept` denotes
1686
  `forward_iterator_tag`.
1687
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
1688
 
 
 
 
1689
  `iterator::iterator_category` is defined as follows:
1690
 
1691
  - Let *OUTERC* denote
1692
  `iterator_traits<iterator_t<Base>>::iterator_category`, and let
1693
  *INNERC* denote
1694
  `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
1695
- - If *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC* each model
1696
- `derived_from<bidirectional_iterator_tag>`, `iterator_category`
 
1697
  denotes `bidirectional_iterator_tag`.
1698
- - Otherwise, if *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC*
1699
- each model `derived_from<forward_iterator_tag>`, `iterator_category`
1700
- denotes `forward_iterator_tag`.
1701
  - Otherwise, if *OUTERC* and *INNERC* each model
1702
- `derived_from<input_iterator_tag>`, `iterator_category` denotes
1703
- `input_iterator_tag`.
1704
- - Otherwise, `iterator_category` denotes `output_iterator_tag`.
1705
 
1706
  `iterator::difference_type` denotes the type:
1707
 
1708
  ``` cpp
1709
  common_type_t<
@@ -1713,74 +2077,92 @@ common_type_t<
1713
 
1714
  `join_view` iterators use the *`satisfy`* function to skip over empty
1715
  inner ranges.
1716
 
1717
  ``` cpp
1718
- constexpr void satisfy(); // exposition only
 
 
 
 
 
 
 
 
1719
  ```
1720
 
1721
  *Effects:* Equivalent to:
1722
 
1723
  ``` cpp
1724
- auto update_inner = [this](range_reference_t<Base> x) -> auto& {
1725
- if constexpr (ref-is-glvalue) // x is a reference
1726
- return x;
1727
  else
1728
- return (parent_->inner_ = views::all(std::move(x)));
1729
  };
1730
 
1731
- for (; outer_ != ranges::end(parent_->base_); ++outer_) {
1732
- auto& inner = update_inner(*outer_);
1733
  inner_ = ranges::begin(inner);
1734
- if (inner_ != ranges::end(inner))
1735
  return;
1736
  }
1737
  if constexpr (ref-is-glvalue)
1738
- inner_ = iterator_t<range_reference_t<Base>>();
1739
  ```
1740
 
1741
  ``` cpp
1742
- constexpr iterator(Parent& parent, iterator_t<Base> outer);
 
1743
  ```
1744
 
1745
  *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
1746
  with `addressof(parent)`; then calls *`satisfy`*`()`.
1747
 
 
 
 
 
 
 
 
 
1748
  ``` cpp
1749
  constexpr iterator(iterator<!Const> i)
1750
  requires Const &&
1751
- convertible_to<iterator_t<V>, iterator_t<Base>> &&
1752
- convertible_to<iterator_t<InnerRng>,
1753
- iterator_t<range_reference_t<Base>>>;
1754
  ```
1755
 
1756
  *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
1757
  *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
1758
  `i.`*`parent_`*.
1759
 
 
 
 
1760
  ``` cpp
1761
- constexpr iterator_t<Base> operator->() const
1762
- requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
1763
  ```
1764
 
1765
- *Effects:* Equivalent to `return `*`inner_`*`;`
1766
 
1767
  ``` cpp
1768
  constexpr iterator& operator++();
1769
  ```
1770
 
1771
  Let *`inner-range`* be:
1772
 
1773
- - If *ref-is-glvalue* is `true`, `*`*`outer_`*.
1774
- - Otherwise, *`parent_`*`->`*`inner_`*.
1775
 
1776
  *Effects:* Equivalent to:
1777
 
1778
  ``` cpp
1779
- auto&& inner_rng = inner-range;
1780
- if (++inner_ == ranges::end(inner_rng)) {
1781
- ++outer_;
1782
  satisfy();
1783
  }
1784
  return *this;
1785
  ```
1786
 
@@ -1813,14 +2195,14 @@ constexpr iterator& operator--()
1813
 
1814
  *Effects:* Equivalent to:
1815
 
1816
  ``` cpp
1817
  if (outer_ == ranges::end(parent_->base_))
1818
- inner_ = ranges::end(*--outer_);
1819
- while (inner_ == ranges::begin(*outer_))
1820
- inner_ = ranges::end(*--outer_);
1821
- --inner_;
1822
  return *this;
1823
  ```
1824
 
1825
  ``` cpp
1826
  constexpr iterator operator--(int)
@@ -1837,48 +2219,573 @@ auto tmp = *this;
1837
  return tmp;
1838
  ```
1839
 
1840
  ``` cpp
1841
  friend constexpr bool operator==(const iterator& x, const iterator& y)
1842
- requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
1843
  equality_comparable<iterator_t<range_reference_t<Base>>>;
1844
  ```
1845
 
1846
  *Effects:* Equivalent to:
1847
  `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
1848
 
1849
  ``` cpp
1850
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
1851
- noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
 
1852
  ```
1853
 
1854
  *Effects:* Equivalent to:
1855
- `return ranges::iter_swap(x.`*`inner_`*`, y.`*`inner_`*`);`
1856
 
1857
  #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
1858
 
1859
  ``` cpp
1860
  namespace std::ranges {
1861
  template<input_range V>
1862
- requires view<V> && input_range<range_reference_t<V>> &&
1863
- (is_reference_v<range_reference_t<V>> ||
1864
- view<range_value_t<V>>)
1865
  template<bool Const>
1866
  struct join_view<V>::sentinel {
1867
  private:
1868
- using Parent = // exposition only
1869
- conditional_t<Const, const join_view, join_view>;
1870
- using Base = conditional_t<Const, const V, V>; // exposition only
1871
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
1872
  public:
1873
  sentinel() = default;
1874
 
1875
  constexpr explicit sentinel(Parent& parent);
1876
  constexpr sentinel(sentinel<!Const> s)
1877
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1878
 
1879
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1880
  };
1881
  }
1882
  ```
1883
 
1884
  ``` cpp
@@ -1893,44 +2800,45 @@ constexpr sentinel(sentinel<!Const> s)
1893
  ```
1894
 
1895
  *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
1896
 
1897
  ``` cpp
1898
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
1899
  ```
1900
 
1901
- *Effects:* Equivalent to: `return x.`*`outer_`*` == y.`*`end_`*`;`
1902
 
1903
- ### Split view <a id="range.split">[[range.split]]</a>
1904
 
1905
- #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
1906
 
1907
- `split_view` takes a `view` and a delimiter, and splits the `view` into
1908
  subranges on the delimiter. The delimiter can be a single element or a
1909
- `view` of elements.
1910
 
1911
- The name `views::split` denotes a range adaptor object
1912
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1913
- expression `views::split(E, F)` is expression-equivalent to
1914
- `split_view{E, F}`.
1915
 
1916
  [*Example 1*:
1917
 
1918
  ``` cpp
1919
  string str{"the quick brown fox"};
1920
- split_view sentence{str, ' '};
1921
- for (auto word : sentence) {
1922
  for (char ch : word)
1923
  cout << ch;
1924
  cout << '*';
1925
  }
1926
- // The above prints: the*quick*brown*fox*
1927
  ```
1928
 
1929
  — *end example*]
1930
 
1931
- #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
1932
 
1933
  ``` cpp
1934
  namespace std::ranges {
1935
  template<auto> struct require-constant; // exposition only
1936
 
@@ -1942,46 +2850,54 @@ namespace std::ranges {
1942
 
1943
  template<input_range V, forward_range Pattern>
1944
  requires view<V> && view<Pattern> &&
1945
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
1946
  (forward_range<V> || tiny-range<Pattern>)
1947
- class split_view : public view_interface<split_view<V, Pattern>> {
1948
  private:
1949
  V base_ = V(); // exposition only
1950
  Pattern pattern_ = Pattern(); // exposition only
1951
- iterator_t<V> current_ = iterator_t<V>(); // exposition only, present only if !forward_range<V>
1952
- // [range.split.outer], class template split_view::outer-iterator
 
 
 
1953
  template<bool> struct outer-iterator; // exposition only
1954
- // [range.split.inner], class template split_view::inner-iterator
 
1955
  template<bool> struct inner-iterator; // exposition only
 
1956
  public:
1957
- split_view() = default;
1958
- constexpr split_view(V base, Pattern pattern);
 
1959
 
1960
  template<input_range R>
1961
  requires constructible_from<V, views::all_t<R>> &&
1962
  constructible_from<Pattern, single_view<range_value_t<R>>>
1963
- constexpr split_view(R&& r, range_value_t<R> e);
1964
 
1965
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1966
  constexpr V base() && { return std::move(base_); }
1967
 
1968
  constexpr auto begin() {
1969
- if constexpr (forward_range<V>)
1970
- return outer-iterator<simple-view<V>>{*this, ranges::begin(base_)};
1971
- else {
 
1972
  current_ = ranges::begin(base_);
1973
  return outer-iterator<false>{*this};
1974
  }
1975
  }
1976
 
1977
  constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
1978
  return outer-iterator<true>{*this, ranges::begin(base_)};
1979
  }
1980
 
1981
  constexpr auto end() requires forward_range<V> && common_range<V> {
1982
- return outer-iterator<simple-view<V>>{*this, ranges::end(base_)};
 
1983
  }
1984
 
1985
  constexpr auto end() const {
1986
  if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
1987
  return outer-iterator<true>{*this, ranges::end(base_)};
@@ -1989,59 +2905,63 @@ namespace std::ranges {
1989
  return default_sentinel;
1990
  }
1991
  };
1992
 
1993
  template<class R, class P>
1994
- split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
1995
 
1996
  template<input_range R>
1997
- split_view(R&&, range_value_t<R>)
1998
- -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
1999
  }
2000
  ```
2001
 
2002
  ``` cpp
2003
- constexpr split_view(V base, Pattern pattern);
2004
  ```
2005
 
2006
  *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
2007
  with `std::move(pattern)`.
2008
 
2009
  ``` cpp
2010
  template<input_range R>
2011
  requires constructible_from<V, views::all_t<R>> &&
2012
  constructible_from<Pattern, single_view<range_value_t<R>>>
2013
- constexpr split_view(R&& r, range_value_t<R> e);
2014
  ```
2015
 
2016
  *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
2017
- and *pattern\_* with `single_view{std::move(e)}`.
2018
 
2019
- #### Class template `split_view::outer-iterator` <a id="range.split.outer">[[range.split.outer]]</a>
2020
 
2021
  ``` cpp
2022
  namespace std::ranges {
2023
  template<input_range V, forward_range Pattern>
2024
  requires view<V> && view<Pattern> &&
2025
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2026
  (forward_range<V> || tiny-range<Pattern>)
2027
  template<bool Const>
2028
- struct split_view<V, Pattern>::outer-iterator {
2029
  private:
2030
- using Parent = // exposition only
2031
- conditional_t<Const, const split_view, split_view>;
2032
- using Base = // exposition only
2033
- conditional_t<Const, const V, V>;
2034
  Parent* parent_ = nullptr; // exposition only
2035
- iterator_t<Base> current_ = // exposition only, present only if V models forward_range
2036
- iterator_t<Base>();
 
 
 
2037
 
2038
  public:
2039
  using iterator_concept =
2040
  conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
2041
- using iterator_category = input_iterator_tag;
2042
- // [range.split.outer.value], class split_view::outer-iterator::value_type
 
 
 
2043
  struct value_type;
2044
  using difference_type = range_difference_t<Base>;
2045
 
2046
  outer-iterator() = default;
2047
  constexpr explicit outer-iterator(Parent& parent)
@@ -2069,13 +2989,14 @@ namespace std::ranges {
2069
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
2070
  };
2071
  }
2072
  ```
2073
 
2074
- Many of the following specifications refer to the notional member
2075
- *current* of *`outer-iterator`*. *current* is equivalent to *`current_`*
2076
- if `V` models `forward_range`, and `parent_->current_` otherwise.
 
2077
 
2078
  ``` cpp
2079
  constexpr explicit outer-iterator(Parent& parent)
2080
  requires (!forward_range<Base>);
2081
  ```
@@ -2110,18 +3031,31 @@ constexpr outer-iterator& operator++();
2110
 
2111
  *Effects:* Equivalent to:
2112
 
2113
  ``` cpp
2114
  const auto end = ranges::end(parent_->base_);
2115
- if (current == end) return *this;
 
 
 
2116
  const auto [pbegin, pend] = subrange{parent_->pattern_};
2117
  if (pbegin == pend) ++current;
 
 
 
 
 
 
 
 
2118
  else {
2119
  do {
2120
- auto [b, p] = ranges::mismatch(std::move(current), end, pbegin, pend);
2121
- current = std::move(b);
2122
  if (p == pend) {
 
 
 
2123
  break; // The pattern matched; skip it
2124
  }
2125
  } while (++current != end);
2126
  }
2127
  return *this;
@@ -2130,39 +3064,46 @@ return *this;
2130
  ``` cpp
2131
  friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
2132
  requires forward_range<Base>;
2133
  ```
2134
 
2135
- *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
 
 
 
 
2136
 
2137
  ``` cpp
2138
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
2139
  ```
2140
 
2141
  *Effects:* Equivalent to:
2142
- `return x.`*`current`*` == ranges::end(x.`*`parent_`*`->`*`base_`*`);`
2143
 
2144
- #### Class `split_view::outer-iterator::value_type` <a id="range.split.outer.value">[[range.split.outer.value]]</a>
 
 
 
 
2145
 
2146
  ``` cpp
2147
  namespace std::ranges {
2148
  template<input_range V, forward_range Pattern>
2149
  requires view<V> && view<Pattern> &&
2150
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2151
  (forward_range<V> || tiny-range<Pattern>)
2152
  template<bool Const>
2153
- struct split_view<V, Pattern>::outer-iterator<Const>::value_type
2154
  : view_interface<value_type> {
2155
  private:
2156
  outer-iterator i_ = outer-iterator(); // exposition only
 
2157
  public:
2158
  value_type() = default;
2159
  constexpr explicit value_type(outer-iterator i);
2160
 
2161
- constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
2162
- constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
2163
- constexpr default_sentinel_t end() const;
2164
  };
2165
  }
2166
  ```
2167
 
2168
  ``` cpp
@@ -2170,57 +3111,56 @@ constexpr explicit value_type(outer-iterator i);
2170
  ```
2171
 
2172
  *Effects:* Initializes *i\_* with `std::move(i)`.
2173
 
2174
  ``` cpp
2175
- constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
2176
  ```
2177
 
2178
  *Effects:* Equivalent to:
2179
  `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
2180
 
2181
  ``` cpp
2182
- constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
2183
- ```
2184
-
2185
- *Effects:* Equivalent to:
2186
- `return `*`inner-iterator`*`<Const>{std::move(`*`i_`*`)};`
2187
-
2188
- ``` cpp
2189
- constexpr default_sentinel_t end() const;
2190
  ```
2191
 
2192
  *Effects:* Equivalent to: `return default_sentinel;`
2193
 
2194
- #### Class template `split_view::inner-iterator` <a id="range.split.inner">[[range.split.inner]]</a>
2195
 
2196
  ``` cpp
2197
  namespace std::ranges {
2198
  template<input_range V, forward_range Pattern>
2199
  requires view<V> && view<Pattern> &&
2200
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2201
  (forward_range<V> || tiny-range<Pattern>)
2202
  template<bool Const>
2203
- struct split_view<V, Pattern>::inner-iterator {
2204
  private:
2205
- using Base = conditional_t<Const, const V, V>; // exposition only
2206
  outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
2207
  bool incremented_ = false; // exposition only
 
2208
  public:
2209
  using iterator_concept = typename outer-iterator<Const>::iterator_concept;
2210
- using iterator_category = see below;
 
 
2211
  using value_type = range_value_t<Base>;
2212
  using difference_type = range_difference_t<Base>;
2213
 
2214
  inner-iterator() = default;
2215
  constexpr explicit inner-iterator(outer-iterator<Const> i);
2216
 
 
 
 
2217
  constexpr decltype(auto) operator*() const { return *i_.current; }
2218
 
2219
  constexpr inner-iterator& operator++();
2220
  constexpr decltype(auto) operator++(int) {
2221
- if constexpr (forward_range<V>) {
2222
  auto tmp = *this;
2223
  ++*this;
2224
  return tmp;
2225
  } else
2226
  ++*this;
@@ -2241,11 +3181,13 @@ namespace std::ranges {
2241
  requires indirectly_swappable<iterator_t<Base>>;
2242
  };
2243
  }
2244
  ```
2245
 
2246
- The *typedef-name* `iterator_category` denotes:
 
 
2247
 
2248
  - `forward_iterator_tag` if
2249
  `iterator_traits<iterator_t<Base>>::iterator_category` models
2250
  `derived_from<forward_iterator_tag>`;
2251
  - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
@@ -2254,10 +3196,22 @@ The *typedef-name* `iterator_category` denotes:
2254
  constexpr explicit inner-iterator(outer-iterator<Const> i);
2255
  ```
2256
 
2257
  *Effects:* Initializes *i\_* with `std::move(i)`.
2258
 
 
 
 
 
 
 
 
 
 
 
 
 
2259
  ``` cpp
2260
  constexpr inner-iterator& operator++();
2261
  ```
2262
 
2263
  *Effects:* Equivalent to:
@@ -2314,13 +3268,264 @@ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y
2314
  ```
2315
 
2316
  *Effects:* Equivalent to
2317
  `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
2318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2319
  ### Counted view <a id="range.counted">[[range.counted]]</a>
2320
 
2321
- A counted view presents a `view` of the elements of the counted range
2322
  [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
2323
  non-negative integer `n`.
2324
 
2325
  The name `views::counted` denotes a customization point object
2326
  [[customization.point.object]]. Let `E` and `F` be expressions, let `T`
@@ -2333,22 +3538,22 @@ be `decay_t<decltype((E))>`, and let `D` be `iter_difference_t<T>`. If
2333
  instantiation. — *end note*]
2334
 
2335
  Otherwise, `views::counted(E, F)` is expression-equivalent to:
2336
 
2337
  - If `T` models `contiguous_iterator`, then
2338
- `span{to_address(E), static_cast<D>(F)}`.
2339
  - Otherwise, if `T` models `random_access_iterator`, then
2340
- `subrange{E, E + static_cast<D>(F)}`, except that `E` is evaluated
2341
  only once.
2342
- - Otherwise, `subrange{counted_iterator{E, F}, default_sentinel}`.
2343
 
2344
  ### Common view <a id="range.common">[[range.common]]</a>
2345
 
2346
  #### Overview <a id="range.common.overview">[[range.common.overview]]</a>
2347
 
2348
- `common_view` takes a `view` which has different types for its iterator
2349
- and sentinel and turns it into a `view` of the same elements with an
2350
  iterator and sentinel of the same type.
2351
 
2352
  [*Note 1*: `common_view` is useful for calling legacy algorithms that
2353
  expect a range’s iterator and sentinel types to be the
2354
  same. — *end note*]
@@ -2368,11 +3573,11 @@ The name `views::common` denotes a range adaptor object
2368
  template<class ForwardIterator>
2369
  size_t count(ForwardIterator first, ForwardIterator last);
2370
 
2371
  template<forward_range R>
2372
  void my_algo(R&& r) {
2373
- auto&& common = common_view{r};
2374
  auto cnt = count(common.begin(), common.end());
2375
  // ...
2376
  }
2377
  ```
2378
 
@@ -2385,19 +3590,16 @@ namespace std::ranges {
2385
  template<view V>
2386
  requires (!common_range<V> && copyable<iterator_t<V>>)
2387
  class common_view : public view_interface<common_view<V>> {
2388
  private:
2389
  V base_ = V(); // exposition only
 
2390
  public:
2391
- common_view() = default;
2392
 
2393
  constexpr explicit common_view(V r);
2394
 
2395
- template<viewable_range R>
2396
- requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
2397
- constexpr explicit common_view(R&& r);
2398
-
2399
  constexpr V base() const & requires copy_constructible<V> { return base_; }
2400
  constexpr V base() && { return std::move(base_); }
2401
 
2402
  constexpr auto begin() {
2403
  if constexpr (random_access_range<V> && sized_range<V>)
@@ -2413,18 +3615,18 @@ namespace std::ranges {
2413
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
2414
  }
2415
 
2416
  constexpr auto end() {
2417
  if constexpr (random_access_range<V> && sized_range<V>)
2418
- return ranges::begin(base_) + ranges::size(base_);
2419
  else
2420
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
2421
  }
2422
 
2423
  constexpr auto end() const requires range<const V> {
2424
  if constexpr (random_access_range<const V> && sized_range<const V>)
2425
- return ranges::begin(base_) + ranges::size(base_);
2426
  else
2427
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
2428
  }
2429
 
2430
  constexpr auto size() requires sized_range<V> {
@@ -2444,37 +3646,26 @@ namespace std::ranges {
2444
  constexpr explicit common_view(V base);
2445
  ```
2446
 
2447
  *Effects:* Initializes *base\_* with `std::move(base)`.
2448
 
2449
- ``` cpp
2450
- template<viewable_range R>
2451
- requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
2452
- constexpr explicit common_view(R&& r);
2453
- ```
2454
-
2455
- *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`.
2456
-
2457
  ### Reverse view <a id="range.reverse">[[range.reverse]]</a>
2458
 
2459
  #### Overview <a id="range.reverse.overview">[[range.reverse.overview]]</a>
2460
 
2461
- `reverse_view` takes a bidirectional `view` and produces another `view`
2462
- that iterates the same elements in reverse order.
2463
 
2464
  The name `views::reverse` denotes a range adaptor object
2465
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
2466
  `views::reverse(E)` is expression-equivalent to:
2467
 
2468
  - If the type of `E` is a (possibly cv-qualified) specialization of
2469
  `reverse_view`, equivalent to `E.base()`.
2470
- - Otherwise, if the type of `E` is cv-qualified
2471
- ``` cpp
2472
- subrange<reverse_iterator<I>, reverse_iterator<I>, K>
2473
- ```
2474
-
2475
- for some iterator type `I` and value `K` of type `subrange_kind`,
2476
  - if `K` is `subrange_kind::sized`, equivalent to:
2477
  ``` cpp
2478
  subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
2479
  ```
2480
  - otherwise, equivalent to:
@@ -2487,13 +3678,12 @@ The name `views::reverse` denotes a range adaptor object
2487
 
2488
  [*Example 1*:
2489
 
2490
  ``` cpp
2491
  vector<int> is {0,1,2,3,4};
2492
- reverse_view rv {is};
2493
- for (int i : rv)
2494
- cout << i << ' '; // prints: 4 3 2 1 0
2495
  ```
2496
 
2497
  — *end example*]
2498
 
2499
  #### Class template `reverse_view` <a id="range.reverse.view">[[range.reverse.view]]</a>
@@ -2503,12 +3693,13 @@ namespace std::ranges {
2503
  template<view V>
2504
  requires bidirectional_range<V>
2505
  class reverse_view : public view_interface<reverse_view<V>> {
2506
  private:
2507
  V base_ = V(); // exposition only
 
2508
  public:
2509
- reverse_view() = default;
2510
 
2511
  constexpr explicit reverse_view(V r);
2512
 
2513
  constexpr V base() const & requires copy_constructible<V> { return base_; }
2514
  constexpr V base() && { return std::move(base_); }
@@ -2521,10 +3712,11 @@ namespace std::ranges {
2521
  constexpr auto end() const requires common_range<const V>;
2522
 
2523
  constexpr auto size() requires sized_range<V> {
2524
  return ranges::size(base_);
2525
  }
 
2526
  constexpr auto size() const requires sized_range<const V> {
2527
  return ranges::size(base_);
2528
  }
2529
  };
2530
 
@@ -2557,27 +3749,101 @@ the `reverse_view` for use on subsequent calls.
2557
  constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
2558
  constexpr auto begin() const requires common_range<const V>;
2559
  ```
2560
 
2561
  *Effects:* Equivalent to:
2562
- `return make_reverse_iterator(ranges::end(base_));`
2563
 
2564
  ``` cpp
2565
  constexpr reverse_iterator<iterator_t<V>> end();
2566
  constexpr auto end() const requires common_range<const V>;
2567
  ```
2568
 
2569
  *Effects:* Equivalent to:
2570
- `return make_reverse_iterator(ranges::begin(base_));`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2571
 
2572
  ### Elements view <a id="range.elements">[[range.elements]]</a>
2573
 
2574
  #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
2575
 
2576
- `elements_view` takes a `view` of tuple-like values and a `size_t`, and
2577
- produces a `view` with a value-type of the Nᵗʰ element of the adapted
2578
- `view`’s value-type.
2579
 
2580
  The name `views::elements<N>` denotes a range adaptor object
2581
  [[range.adaptor.object]]. Given a subexpression `E` and constant
2582
  expression `N`, the expression `views::elements<N>(E)` is
2583
  expression-equivalent to
@@ -2585,11 +3851,11 @@ expression-equivalent to
2585
 
2586
  [*Example 1*:
2587
 
2588
  ``` cpp
2589
  auto historical_figures = map{
2590
- {"Lovelace"sv, 1815},
2591
  {"Turing"sv, 1912},
2592
  {"Babbage"sv, 1791},
2593
  {"Hamilton"sv, 1936}
2594
  };
2595
 
@@ -2604,71 +3870,70 @@ for (auto&& born : birth_years) {
2604
  }
2605
  ```
2606
 
2607
  — *end example*]
2608
 
2609
- `keys_view` is an alias for `elements_view<views::all_t<R>, 0>`, and is
2610
- useful for extracting keys from associative containers.
2611
 
2612
  [*Example 2*:
2613
 
2614
  ``` cpp
2615
- auto names = keys_view{historical_figures};
2616
  for (auto&& name : names) {
2617
  cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
2618
  }
2619
  ```
2620
 
2621
  — *end example*]
2622
 
2623
- `values_view` is an alias for `elements_view<views::all_t<R>, 1>`, and
2624
- is useful for extracting values from associative containers.
2625
 
2626
  [*Example 3*:
2627
 
2628
  ``` cpp
2629
  auto is_even = [](const auto x) { return x % 2 == 0; };
2630
- cout << ranges::count_if(values_view{historical_figures}, is_even); // prints 2
2631
  ```
2632
 
2633
  — *end example*]
2634
 
2635
  #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
2636
 
2637
  ``` cpp
2638
  namespace std::ranges {
2639
  template<class T, size_t N>
2640
  concept has-tuple-element = // exposition only
2641
- requires(T t) {
2642
- typename tuple_size<T>::type;
2643
- requires N < tuple_size_v<T>;
2644
- typename tuple_element_t<N, T>;
2645
- { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
2646
- };
2647
 
 
 
 
2648
 
2649
  template<input_range V, size_t N>
2650
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
2651
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
2652
  class elements_view : public view_interface<elements_view<V, N>> {
2653
  public:
2654
- elements_view() = default;
2655
  constexpr explicit elements_view(V base);
2656
 
2657
  constexpr V base() const & requires copy_constructible<V> { return base_; }
2658
  constexpr V base() && { return std::move(base_); }
2659
 
2660
  constexpr auto begin() requires (!simple-view<V>)
2661
  { return iterator<false>(ranges::begin(base_)); }
2662
 
2663
- constexpr auto begin() const requires simple-view<V>
2664
  { return iterator<true>(ranges::begin(base_)); }
2665
 
2666
- constexpr auto end()
2667
  { return sentinel<false>{ranges::end(base_)}; }
2668
 
2669
- constexpr auto end() requires common_range<V>
2670
  { return iterator<false>{ranges::end(base_)}; }
2671
 
2672
  constexpr auto end() const requires range<const V>
2673
  { return sentinel<true>{ranges::end(base_)}; }
2674
 
@@ -2681,13 +3946,15 @@ namespace std::ranges {
2681
  constexpr auto size() const requires sized_range<const V>
2682
  { return ranges::size(base_); }
2683
 
2684
  private:
2685
  // [range.elements.iterator], class template elements_view::iterator
2686
- template<bool> struct iterator; // exposition only
 
2687
  // [range.elements.sentinel], class template elements_view::sentinel
2688
- template<bool> struct sentinel; // exposition only
 
2689
  V base_ = V(); // exposition only
2690
  };
2691
  }
2692
  ```
2693
 
@@ -2701,35 +3968,39 @@ constexpr explicit elements_view(V base);
2701
 
2702
  ``` cpp
2703
  namespace std::ranges {
2704
  template<input_range V, size_t N>
2705
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
2706
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
2707
  template<bool Const>
2708
- class elements_view<V, N>::iterator { // exposition only
2709
- using Base = conditional_t<Const, const V, V>; // exposition only
 
 
 
 
2710
 
2711
- iterator_t<Base> current_ = iterator_t<Base>();
2712
  public:
2713
- using iterator_category = typename iterator_traits<iterator_t<Base>>::iterator_category;
 
2714
  using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
2715
  using difference_type = range_difference_t<Base>;
2716
 
2717
- iterator() = default;
2718
  constexpr explicit iterator(iterator_t<Base> current);
2719
  constexpr iterator(iterator<!Const> i)
2720
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2721
 
2722
- constexpr iterator_t<Base> base() const&
2723
- requires copyable<iterator_t<Base>>;
2724
  constexpr iterator_t<Base> base() &&;
2725
 
2726
  constexpr decltype(auto) operator*() const
2727
- { return get<N>(*current_); }
2728
 
2729
  constexpr iterator& operator++();
2730
- constexpr void operator++(int) requires (!forward_range<Base>);
2731
  constexpr iterator operator++(int) requires forward_range<Base>;
2732
 
2733
  constexpr iterator& operator--() requires bidirectional_range<Base>;
2734
  constexpr iterator operator--(int) requires bidirectional_range<Base>;
2735
 
@@ -2738,20 +4009,20 @@ namespace std::ranges {
2738
  constexpr iterator& operator-=(difference_type x)
2739
  requires random_access_range<Base>;
2740
 
2741
  constexpr decltype(auto) operator[](difference_type n) const
2742
  requires random_access_range<Base>
2743
- { return get<N>(*(current_ + n)); }
2744
 
2745
  friend constexpr bool operator==(const iterator& x, const iterator& y)
2746
  requires equality_comparable<iterator_t<Base>>;
2747
 
2748
  friend constexpr bool operator<(const iterator& x, const iterator& y)
2749
  requires random_access_range<Base>;
2750
  friend constexpr bool operator>(const iterator& x, const iterator& y)
2751
  requires random_access_range<Base>;
2752
- friend constexpr bool operator<=(const iterator& y, const iterator& y)
2753
  requires random_access_range<Base>;
2754
  friend constexpr bool operator>=(const iterator& x, const iterator& y)
2755
  requires random_access_range<Base>;
2756
  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
2757
  requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
@@ -2761,15 +4032,51 @@ namespace std::ranges {
2761
  friend constexpr iterator operator+(difference_type x, const iterator& y)
2762
  requires random_access_range<Base>;
2763
  friend constexpr iterator operator-(const iterator& x, difference_type y)
2764
  requires random_access_range<Base>;
2765
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
2766
- requires random_access_range<Base>;
2767
  };
2768
  }
2769
  ```
2770
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2771
  ``` cpp
2772
  constexpr explicit iterator(iterator_t<Base> current);
2773
  ```
2774
 
2775
  *Effects:* Initializes *current\_* with `std::move(current)`.
@@ -2780,12 +4087,11 @@ constexpr iterator(iterator<!Const> i)
2780
  ```
2781
 
2782
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
2783
 
2784
  ``` cpp
2785
- constexpr iterator_t<Base> base() const&
2786
- requires copyable<iterator_t<Base>>;
2787
  ```
2788
 
2789
  *Effects:* Equivalent to: `return `*`current_`*`;`
2790
 
2791
  ``` cpp
@@ -2804,11 +4110,11 @@ constexpr iterator& operator++();
2804
  ++current_;
2805
  return *this;
2806
  ```
2807
 
2808
  ``` cpp
2809
- constexpr void operator++(int) requires (!forward_range<Base>);
2810
  ```
2811
 
2812
  *Effects:* Equivalent to: `++`*`current_`*.
2813
 
2814
  ``` cpp
@@ -2845,11 +4151,11 @@ auto temp = *this;
2845
  --current_;
2846
  return temp;
2847
  ```
2848
 
2849
  ``` cpp
2850
- constexpr iterator& operator+=(difference_type n);
2851
  requires random_access_range<Base>;
2852
  ```
2853
 
2854
  *Effects:* Equivalent to:
2855
 
@@ -2916,62 +4222,68 @@ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
2916
  ``` cpp
2917
  friend constexpr iterator operator+(const iterator& x, difference_type y)
2918
  requires random_access_range<Base>;
2919
  ```
2920
 
2921
- *Effects:* Equivalent to: `return iterator{x} += y;`
2922
 
2923
  ``` cpp
2924
  friend constexpr iterator operator+(difference_type x, const iterator& y)
2925
  requires random_access_range<Base>;
2926
  ```
2927
 
2928
  *Effects:* Equivalent to: `return y + x;`
2929
 
2930
  ``` cpp
2931
- constexpr iterator operator-(const iterator& x, difference_type y)
2932
  requires random_access_range<Base>;
2933
  ```
2934
 
2935
- *Effects:* Equivalent to: `return iterator{x} -= y;`
2936
 
2937
  ``` cpp
2938
- constexpr difference_type operator-(const iterator& x, const iterator& y)
2939
- requires random_access_range<Base>;
2940
  ```
2941
 
2942
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
2943
 
2944
  #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
2945
 
2946
  ``` cpp
2947
  namespace std::ranges {
2948
  template<input_range V, size_t N>
2949
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
2950
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
2951
  template<bool Const>
2952
- class elements_view<V, N>::sentinel { // exposition only
2953
  private:
2954
- using Base = conditional_t<Const, const V, V>; // exposition only
2955
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
2956
  public:
2957
  sentinel() = default;
2958
  constexpr explicit sentinel(sentinel_t<Base> end);
2959
  constexpr sentinel(sentinel<!Const> other)
2960
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
2961
 
2962
  constexpr sentinel_t<Base> base() const;
2963
 
2964
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
2965
 
2966
- friend constexpr range_difference_t<Base>
2967
- operator-(const iterator<Const>& x, const sentinel& y)
2968
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
2969
 
2970
- friend constexpr range_difference_t<Base>
2971
- operator-(const sentinel& x, const iterator<Const>& y)
2972
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
2973
  };
2974
  }
2975
  ```
2976
 
2977
  ``` cpp
@@ -2992,144 +4304,4860 @@ constexpr sentinel_t<Base> base() const;
2992
  ```
2993
 
2994
  *Effects:* Equivalent to: `return `*`end_`*`;`
2995
 
2996
  ``` cpp
2997
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
2998
  ```
2999
 
3000
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
3001
 
3002
  ``` cpp
3003
- friend constexpr range_difference_t<Base>
3004
- operator-(const iterator<Const>& x, const sentinel& y)
3005
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
3006
  ```
3007
 
3008
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
3009
 
3010
  ``` cpp
3011
- friend constexpr range_difference_t<Base>
3012
- operator-(const sentinel& x, const iterator<Const>& y)
3013
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3014
  ```
3015
 
3016
  *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
3017
 
3018
- <!-- Link reference definitions -->
3019
- [basic.compound]: basic.md#basic.compound
3020
- [concepts.equality]: concepts.md#concepts.equality
3021
- [containers]: containers.md#containers
3022
- [conv.rval]: expr.md#conv.rval
3023
- [customization.point.object]: library.md#customization.point.object
3024
- [dcl.array]: dcl.md#dcl.array
3025
- [expr.const]: expr.md#expr.const
3026
- [iterator.concept.bidir]: iterators.md#iterator.concept.bidir
3027
- [iterator.concept.iterator]: iterators.md#iterator.concept.iterator
3028
- [iterator.concept.output]: iterators.md#iterator.concept.output
3029
- [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
3030
- [iterator.concept.sizedsentinel]: iterators.md#iterator.concept.sizedsentinel
3031
- [iterator.concept.winc]: iterators.md#iterator.concept.winc
3032
- [iterator.requirements.general]: iterators.md#iterator.requirements.general
3033
- [namespace.std]: library.md#namespace.std
3034
- [range.access]: #range.access
3035
- [range.access.begin]: #range.access.begin
3036
- [range.access.cbegin]: #range.access.cbegin
3037
- [range.access.cend]: #range.access.cend
3038
- [range.access.crbegin]: #range.access.crbegin
3039
- [range.access.crend]: #range.access.crend
3040
- [range.access.end]: #range.access.end
3041
- [range.access.rbegin]: #range.access.rbegin
3042
- [range.access.rend]: #range.access.rend
3043
- [range.adaptor.object]: #range.adaptor.object
3044
- [range.adaptors]: #range.adaptors
3045
- [range.all]: #range.all
3046
- [range.common]: #range.common
3047
- [range.common.overview]: #range.common.overview
3048
- [range.common.view]: #range.common.view
3049
- [range.counted]: #range.counted
3050
- [range.dangling]: #range.dangling
3051
- [range.drop]: #range.drop
3052
- [range.drop.overview]: #range.drop.overview
3053
- [range.drop.view]: #range.drop.view
3054
- [range.drop.while]: #range.drop.while
3055
- [range.drop.while.overview]: #range.drop.while.overview
3056
- [range.drop.while.view]: #range.drop.while.view
3057
- [range.elements]: #range.elements
3058
- [range.elements.iterator]: #range.elements.iterator
3059
- [range.elements.overview]: #range.elements.overview
3060
- [range.elements.sentinel]: #range.elements.sentinel
3061
- [range.elements.view]: #range.elements.view
3062
- [range.empty]: #range.empty
3063
- [range.empty.overview]: #range.empty.overview
3064
- [range.empty.view]: #range.empty.view
3065
- [range.factories]: #range.factories
3066
- [range.filter]: #range.filter
3067
- [range.filter.iterator]: #range.filter.iterator
3068
- [range.filter.overview]: #range.filter.overview
3069
- [range.filter.sentinel]: #range.filter.sentinel
3070
- [range.filter.view]: #range.filter.view
3071
- [range.iota]: #range.iota
3072
- [range.iota.iterator]: #range.iota.iterator
3073
- [range.iota.overview]: #range.iota.overview
3074
- [range.iota.sentinel]: #range.iota.sentinel
3075
- [range.iota.view]: #range.iota.view
3076
- [range.istream]: #range.istream
3077
- [range.istream.iterator]: #range.istream.iterator
3078
- [range.istream.overview]: #range.istream.overview
3079
- [range.istream.view]: #range.istream.view
3080
- [range.join]: #range.join
3081
- [range.join.iterator]: #range.join.iterator
3082
- [range.join.overview]: #range.join.overview
3083
- [range.join.sentinel]: #range.join.sentinel
3084
- [range.join.view]: #range.join.view
3085
- [range.prim.cdata]: #range.prim.cdata
3086
- [range.prim.data]: #range.prim.data
3087
- [range.prim.empty]: #range.prim.empty
3088
- [range.prim.size]: #range.prim.size
3089
- [range.prim.ssize]: #range.prim.ssize
3090
- [range.range]: #range.range
3091
- [range.ref.view]: #range.ref.view
3092
- [range.refinements]: #range.refinements
3093
- [range.req]: #range.req
3094
- [range.req.general]: #range.req.general
3095
- [range.reverse]: #range.reverse
3096
- [range.reverse.overview]: #range.reverse.overview
3097
- [range.reverse.view]: #range.reverse.view
3098
- [range.semi.wrap]: #range.semi.wrap
3099
- [range.single]: #range.single
3100
- [range.single.overview]: #range.single.overview
3101
- [range.single.view]: #range.single.view
3102
- [range.sized]: #range.sized
3103
- [range.split]: #range.split
3104
- [range.split.inner]: #range.split.inner
3105
- [range.split.outer]: #range.split.outer
3106
- [range.split.outer.value]: #range.split.outer.value
3107
- [range.split.overview]: #range.split.overview
3108
- [range.split.view]: #range.split.view
3109
- [range.subrange]: #range.subrange
3110
- [range.subrange.access]: #range.subrange.access
3111
- [range.subrange.ctor]: #range.subrange.ctor
3112
- [range.summary]: #range.summary
3113
- [range.take]: #range.take
3114
- [range.take.overview]: #range.take.overview
3115
- [range.take.sentinel]: #range.take.sentinel
3116
- [range.take.view]: #range.take.view
3117
- [range.take.while]: #range.take.while
3118
- [range.take.while.overview]: #range.take.while.overview
3119
- [range.take.while.sentinel]: #range.take.while.sentinel
3120
- [range.take.while.view]: #range.take.while.view
3121
- [range.transform]: #range.transform
3122
- [range.transform.iterator]: #range.transform.iterator
3123
- [range.transform.overview]: #range.transform.overview
3124
- [range.transform.sentinel]: #range.transform.sentinel
3125
- [range.transform.view]: #range.transform.view
3126
- [range.utility]: #range.utility
3127
- [range.utility.helpers]: #range.utility.helpers
3128
- [range.view]: #range.view
3129
- [ranges]: #ranges
3130
- [ranges.general]: #ranges.general
3131
- [ranges.syn]: #ranges.syn
3132
- [string.view]: strings.md#string.view
3133
- [view.interface]: #view.interface
3134
- [view.interface.members]: #view.interface.members
3135
- [views.span]: containers.md#views.span
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ## Range adaptors <a id="range.adaptors">[[range.adaptors]]</a>
2
 
3
+ ### General <a id="range.adaptors.general">[[range.adaptors.general]]</a>
4
+
5
+ Subclause [[range.adaptors]] defines *range adaptors*, which are
6
+ utilities that transform a range into a view with custom behaviors.
7
+ These adaptors can be chained to create pipelines of range
8
+ transformations that evaluate lazily as the resulting view is iterated.
9
 
10
  Range adaptors are declared in namespace `std::ranges::views`.
11
 
12
  The bitwise operator is overloaded for the purpose of creating adaptor
13
  chain pipelines. The adaptors also support function call syntax with
 
18
  ``` cpp
19
  vector<int> ints{0,1,2,3,4,5};
20
  auto even = [](int i) { return 0 == i % 2; };
21
  auto square = [](int i) { return i * i; };
22
  for (int i : ints | views::filter(even) | views::transform(square)) {
23
+ cout << i << ' '; // prints 0 4 16
24
  }
25
  assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
26
  ```
27
 
28
  — *end example*]
29
 
30
  ### Range adaptor objects <a id="range.adaptor.object">[[range.adaptor.object]]</a>
31
 
32
  A *range adaptor closure object* is a unary function object that accepts
33
+ a range argument. For a range adaptor closure object `C` and an
34
+ expression `R` such that `decltype((R))` models `range`, the following
35
+ expressions are equivalent:
 
36
 
37
  ``` cpp
38
  C(R)
39
  R | C
40
  ```
41
 
42
  Given an additional range adaptor closure object `D`, the expression
43
+ `C | D` produces another range adaptor closure object `E`. `E` is a
44
+ perfect forwarding call wrapper [[term.perfect.forwarding.call.wrapper]]
45
+ with the following properties:
46
 
47
+ - Its target object is an object `d` of type `decay_t<decltype((D))>`
48
+ direct-non-list-initialized with `D`.
49
+ - It has one bound argument entity, an object `c` of type
50
+ `decay_t<decltype((C))>` direct-non-list-initialized with `C`.
51
+ - Its call pattern is `d(c(arg))`, where `arg` is the argument used in a
52
+ function call expression of `E`.
53
+
54
+ The expression `C | D` is well-formed if and only if the initializations
55
+ of the state entities of `E` are all well-formed.
56
+
57
+ Given an object `t` of type `T`, where
58
+
59
+ - `t` is a unary function object that accepts a range argument,
60
+ - `T` models `derived_from<range_adaptor_closure<T>>`,
61
+ - `T` has no other base classes of type `range_adaptor_closure<U>` for
62
+ any other type `U`, and
63
+ - `T` does not model `range`
64
+
65
+ then the implementation ensures that `t` is a range adaptor closure
66
+ object.
67
+
68
+ The template parameter `D` for `range_adaptor_closure` may be an
69
+ incomplete type. If an expression of type cv `D` is used as an operand
70
+ to the `|` operator, `D` shall be complete and model
71
+ `derived_from<range_adaptor_closure<D>>`. The behavior of an expression
72
+ involving an object of type cv `D` as an operand to the `|` operator is
73
+ undefined if overload resolution selects a program-defined `operator|`
74
+ function.
75
+
76
+ If an expression of type cv `U` is used as an operand to the `|`
77
+ operator, where `U` has a base class of type `range_adaptor_closure<T>`
78
+ for some type `T` other than `U`, the behavior is undefined.
79
+
80
+ The behavior of a program that adds a specialization for
81
+ `range_adaptor_closure` is undefined.
82
 
83
  A *range adaptor object* is a customization point object
84
  [[customization.point.object]] that accepts a `viewable_range` as its
85
+ first argument and returns a view.
86
 
87
  If a range adaptor object accepts only one argument, then it is a range
88
  adaptor closure object.
89
 
90
+ If a range adaptor object `adaptor` accepts more than one argument, then
91
+ let `range` be an expression such that `decltype((range))` models
92
+ `viewable_range`, let `args...` be arguments such that
93
+ `adaptor(range, args...)` is a well-formed expression as specified in
94
+ the rest of subclause  [[range.adaptors]], and let `BoundArgs` be a pack
95
+ that denotes `decay_t<decltype((args))>...`. The expression
96
+ `adaptor(args...)` produces a range adaptor closure object `f` that is a
97
+ perfect forwarding call wrapper [[term.perfect.forwarding.call.wrapper]]
98
+ with the following properties:
99
 
100
+ - Its target object is a copy of `adaptor`.
101
+ - Its bound argument entities `bound_args` consist of objects of types
102
+ `BoundArgs...` direct-non-list-initialized with
103
+ `std::forward<decltype((args))>(args)...`, respectively.
104
+ - Its call pattern is `adaptor(r, bound_args...)`, where `r` is the
105
+ argument used in a function call expression of `f`.
106
 
107
+ The expression `adaptor(args...)` is well-formed if and only if the
108
+ initialization of the bound argument entities of the result, as
109
+ specified above, are all well-formed.
110
 
111
+ ### Movable wrapper <a id="range.move.wrap">[[range.move.wrap]]</a>
112
 
113
  Many types in this subclause are specified in terms of an
114
+ exposition-only class template *`movable-box`*. `movable-box<T>` behaves
115
+ exactly like `optional<T>` with the following differences:
116
 
117
+ - `movable-box<T>` constrains its type parameter `T` with
118
+ `move_constructible<T> && is_object_v<T>`.
119
+ - The default constructor of `movable-box<T>` is equivalent to:
 
120
  ``` cpp
121
+ constexpr movable-box() noexcept(is_nothrow_default_constructible_v<T>)
122
+ requires default_initializable<T>
123
+ : movable-box{in_place} {}
124
  ```
125
+ - If `copyable<T>` is not modeled, the copy assignment operator is
126
+ equivalent to:
127
  ``` cpp
128
+ constexpr movable-box& operator=(const movable-box& that)
129
  noexcept(is_nothrow_copy_constructible_v<T>)
130
+ requires copy_constructible<T> {
131
+ if (this != addressof(that)) {
132
  if (that) emplace(*that);
133
  else reset();
134
+ }
135
  return *this;
136
  }
137
  ```
138
+ - If `movable<T>` is not modeled, the move assignment operator is
139
+ equivalent to:
140
  ``` cpp
141
+ constexpr movable-box& operator=(movable-box&& that)
142
+ noexcept(is_nothrow_move_constructible_v<T>) {
143
+ if (this != addressof(that)) {
144
  if (that) emplace(std::move(*that));
145
  else reset();
146
+ }
147
  return *this;
148
  }
149
  ```
150
 
151
+ *Recommended practice:*
152
+
153
+ - If `copy_constructible<T>` is `true`, `movable-box<T>` should store
154
+ only a `T` if either `T` models `copyable`, or
155
+ `is_nothrow_move_constructible_v<T> && is_nothrow_copy_constructible_v<T>`
156
+ is `true`.
157
+ - Otherwise, `movable-box<T>` should store only a `T` if either `T`
158
+ models `movable` or `is_nothrow_move_constructible_v<T>` is `true`.
159
+
160
+ ### Non-propagating cache <a id="range.nonprop.cache">[[range.nonprop.cache]]</a>
161
+
162
+ Some types in subclause [[range.adaptors]] are specified in terms of an
163
+ exposition-only class template *`non-propagating-{}cache`*.
164
+ `non-propagating-cache<T>` behaves exactly like `optional<T>` with the
165
+ following differences:
166
+
167
+ - `non-propagating-cache<T>` constrains its type parameter `T` with
168
+ `is_object_v<T>`.
169
+ - The copy constructor is equivalent to:
170
+ ``` cpp
171
+ constexpr non-propagating-cache(const non-propagating-cache&) noexcept {}
172
+ ```
173
+ - The move constructor is equivalent to:
174
+ ``` cpp
175
+ constexpr non-propagating-cache(non-propagating-cache&& other) noexcept {
176
+ other.reset();
177
+ }
178
+ ```
179
+ - The copy assignment operator is equivalent to:
180
+ ``` cpp
181
+ constexpr non-propagating-cache& operator=(const non-propagating-cache& other) noexcept {
182
+ if (addressof(other) != this)
183
+ reset();
184
+ return *this;
185
+ }
186
+ ```
187
+ - The move assignment operator is equivalent to:
188
+ ``` cpp
189
+ constexpr non-propagating-cache& operator=(non-propagating-cache&& other) noexcept {
190
+ reset();
191
+ other.reset();
192
+ return *this;
193
+ }
194
+ ```
195
+ - `non-propagating-cache<T>` has an additional member function template
196
+ specified as follows:
197
+ ``` cpp
198
+ template<class I>
199
+ constexpr T& emplace-deref(const I& i); // exposition only
200
+ ```
201
+
202
+ *Mandates:* The declaration `T t(*i);` is well-formed for some
203
+ invented variable `t`.
204
+ \[*Note 1*: If `*i` is a prvalue of type cv `T`, there is no
205
+ requirement that it is movable [[dcl.init.general]]. — *end note*]
206
+ *Effects:* Calls `reset()`. Then direct-non-list-initializes the
207
+ contained value with `*i`.
208
+ *Ensures:* `*this` contains a value.
209
+ *Returns:* A reference to the new contained value.
210
+ *Throws:* Any exception thrown by the initialization of the contained
211
+ value.
212
+ *Remarks:* If an exception is thrown during the initialization of `T`,
213
+ `*this` does not contain a value, and the previous value (if any) has
214
+ been destroyed.
215
+
216
+ [*Note 1*: *`non-propagating-cache`* enables an input view to
217
+ temporarily cache values as it is iterated over. — *end note*]
218
+
219
+ ### Range adaptor helpers <a id="range.adaptor.helpers">[[range.adaptor.helpers]]</a>
220
+
221
+ ``` cpp
222
+ namespace std::ranges {
223
+ template<class F, class Tuple>
224
+ constexpr auto tuple-transform(F&& f, Tuple&& t) { // exposition only
225
+ return apply([&]<class... Ts>(Ts&&... elements) {
226
+ return tuple<invoke_result_t<F&, Ts>...>(invoke(f, std::forward<Ts>(elements))...);
227
+ }, std::forward<Tuple>(t));
228
+ }
229
+
230
+ template<class F, class Tuple>
231
+ constexpr void tuple-for-each(F&& f, Tuple&& t) { // exposition only
232
+ apply([&]<class... Ts>(Ts&&... elements) {
233
+ (static_cast<void>(invoke(f, std::forward<Ts>(elements))), ...);
234
+ }, std::forward<Tuple>(t));
235
+ }
236
+
237
+ template<class T>
238
+ constexpr T& as-lvalue(T&& t) { // exposition only
239
+ return static_cast<T&>(t);
240
+ }
241
+ }
242
+ ```
243
+
244
  ### All view <a id="range.all">[[range.all]]</a>
245
 
246
+ #### General <a id="range.all.general">[[range.all.general]]</a>
247
+
248
+ `views::all` returns a view that includes all elements of its range
249
  argument.
250
 
251
  The name `views::all` denotes a range adaptor object
252
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
253
  `views::all(E)` is expression-equivalent to:
254
 
255
  - `decay-copy(E)` if the decayed type of `E` models `view`.
256
  - Otherwise, `ref_view{E}` if that expression is well-formed.
257
+ - Otherwise, `owning_view{E}`.
258
 
259
  #### Class template `ref_view` <a id="range.ref.view">[[range.ref.view]]</a>
260
 
261
+ `ref_view` is a view of the elements of some other range.
262
 
263
  ``` cpp
264
  namespace std::ranges {
265
  template<range R>
266
  requires is_object_v<R>
267
  class ref_view : public view_interface<ref_view<R>> {
268
  private:
269
+ R* r_; // exposition only
 
 
270
 
271
+ public:
272
+ template<different-from<ref_view> T>
273
  requires see below
274
  constexpr ref_view(T&& t);
275
 
276
  constexpr R& base() const { return *r_; }
277
 
 
286
  { return ranges::size(*r_); }
287
 
288
  constexpr auto data() const requires contiguous_range<R>
289
  { return ranges::data(*r_); }
290
  };
291
+
292
  template<class R>
293
  ref_view(R&) -> ref_view<R>;
294
  }
295
  ```
296
 
297
  ``` cpp
298
+ template<different-from<ref_view> T>
299
  requires see below
300
  constexpr ref_view(T&& t);
301
  ```
302
 
303
+ *Effects:* Initializes *r\_* with
304
+ `addressof(static_cast<R&>(std::forward<T>(t)))`.
305
+
306
  *Remarks:* Let *`FUN`* denote the exposition-only functions
307
 
308
  ``` cpp
309
  void FUN(R&);
310
  void FUN(R&&) = delete;
311
  ```
312
 
313
+ The expression in the *requires-clause* is equivalent to:
314
 
315
  ``` cpp
316
  convertible_to<T, R&> && requires { FUN(declval<T>()); }
317
  ```
318
 
319
+ #### Class template `owning_view` <a id="range.owning.view">[[range.owning.view]]</a>
320
+
321
+ `owning_view` is a move-only view of the elements of some other range.
322
+
323
+ ``` cpp
324
+ namespace std::ranges {
325
+ template<range R>
326
+ requires movable<R> && (!is-initializer-list<R>) // see [range.refinements]
327
+ class owning_view : public view_interface<owning_view<R>> {
328
+ private:
329
+ R r_ = R(); // exposition only
330
+
331
+ public:
332
+ owning_view() requires default_initializable<R> = default;
333
+ constexpr owning_view(R&& t);
334
+
335
+ owning_view(owning_view&&) = default;
336
+ owning_view& operator=(owning_view&&) = default;
337
+
338
+ constexpr R& base() & noexcept { return r_; }
339
+ constexpr const R& base() const & noexcept { return r_; }
340
+ constexpr R&& base() && noexcept { return std::move(r_); }
341
+ constexpr const R&& base() const && noexcept { return std::move(r_); }
342
+
343
+ constexpr iterator_t<R> begin() { return ranges::begin(r_); }
344
+ constexpr sentinel_t<R> end() { return ranges::end(r_); }
345
+
346
+ constexpr auto begin() const requires range<const R>
347
+ { return ranges::begin(r_); }
348
+ constexpr auto end() const requires range<const R>
349
+ { return ranges::end(r_); }
350
+
351
+ constexpr bool empty() requires requires { ranges::empty(r_); }
352
+ { return ranges::empty(r_); }
353
+ constexpr bool empty() const requires requires { ranges::empty(r_); }
354
+ { return ranges::empty(r_); }
355
+
356
+ constexpr auto size() requires sized_range<R>
357
+ { return ranges::size(r_); }
358
+ constexpr auto size() const requires sized_range<const R>
359
+ { return ranges::size(r_); }
360
+
361
+ constexpr auto data() requires contiguous_range<R>
362
+ { return ranges::data(r_); }
363
+ constexpr auto data() const requires contiguous_range<const R>
364
+ { return ranges::data(r_); }
365
+ };
366
+ }
367
+ ```
368
+
369
+ ``` cpp
370
+ constexpr owning_view(R&& t);
371
+ ```
372
+
373
+ *Effects:* Initializes *r\_* with `std::move(t)`.
374
+
375
+ ### As rvalue view <a id="range.as.rvalue">[[range.as.rvalue]]</a>
376
+
377
+ #### Overview <a id="range.as.rvalue.overview">[[range.as.rvalue.overview]]</a>
378
+
379
+ `as_rvalue_view` presents a view of an underlying sequence with the same
380
+ behavior as the underlying sequence except that its elements are
381
+ rvalues. Some generic algorithms can be called with an `as_rvalue_view`
382
+ to replace copying with moving.
383
+
384
+ The name `views::as_rvalue` denotes a range adaptor object
385
+ [[range.adaptor.object]]. Let `E` be an expression and let `T` be
386
+ `decltype((E))`. The expression `views::as_rvalue(E)` is
387
+ expression-equivalent to:
388
+
389
+ - `views::all(E)` if
390
+ `same_as<range_rvalue_reference_t<T>, range_reference_t<T>>` is
391
+ `true`.
392
+ - Otherwise, `as_rvalue_view(E)`.
393
+
394
+ [*Example 1*:
395
+
396
+ ``` cpp
397
+ vector<string> words = {"the", "quick", "brown", "fox", "ate", "a", "pterodactyl"};
398
+ vector<string> new_words;
399
+ ranges::copy(words | views::as_rvalue, back_inserter(new_words));
400
+ // moves each string from words into new_words
401
+ ```
402
+
403
+ — *end example*]
404
+
405
+ #### Class template `as_rvalue_view` <a id="range.as.rvalue.view">[[range.as.rvalue.view]]</a>
406
+
407
+ ``` cpp
408
+ namespace std::ranges {
409
+ template<view V>
410
+ requires input_range<V>
411
+ class as_rvalue_view : public view_interface<as_rvalue_view<V>> {
412
+ V base_ = V(); // exposition only
413
+
414
+ public:
415
+ as_rvalue_view() requires default_initializable<V> = default;
416
+ constexpr explicit as_rvalue_view(V base);
417
+
418
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
419
+ constexpr V base() && { return std::move(base_); }
420
+
421
+ constexpr auto begin() requires (!simple-view<V>)
422
+ { return move_iterator(ranges::begin(base_)); }
423
+ constexpr auto begin() const requires range<const V>
424
+ { return move_iterator(ranges::begin(base_)); }
425
+
426
+ constexpr auto end() requires (!simple-view<V>) {
427
+ if constexpr (common_range<V>) {
428
+ return move_iterator(ranges::end(base_));
429
+ } else {
430
+ return move_sentinel(ranges::end(base_));
431
+ }
432
+ }
433
+ constexpr auto end() const requires range<const V> {
434
+ if constexpr (common_range<const V>) {
435
+ return move_iterator(ranges::end(base_));
436
+ } else {
437
+ return move_sentinel(ranges::end(base_));
438
+ }
439
+ }
440
+
441
+ constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
442
+ constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
443
+ };
444
+
445
+ template<class R>
446
+ as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>;
447
+ }
448
+ ```
449
+
450
+ ``` cpp
451
+ constexpr explicit as_rvalue_view(V base);
452
+ ```
453
+
454
+ *Effects:* Initializes *base\_* with `std::move(base)`.
455
 
456
  ### Filter view <a id="range.filter">[[range.filter]]</a>
457
 
458
  #### Overview <a id="range.filter.overview">[[range.filter.overview]]</a>
459
 
460
+ `filter_view` presents a view of the elements of an underlying sequence
461
+ that satisfy a predicate.
462
 
463
  The name `views::filter` denotes a range adaptor object
464
  [[range.adaptor.object]]. Given subexpressions `E` and `P`, the
465
  expression `views::filter(E, P)` is expression-equivalent to
466
+ `filter_view(E, P)`.
467
 
468
  [*Example 1*:
469
 
470
  ``` cpp
471
  vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
472
+ auto evens = views::filter(is, [](int i) { return 0 == i % 2; });
473
  for (int i : evens)
474
+ cout << i << ' '; // prints 0 2 4 6
475
  ```
476
 
477
  — *end example*]
478
 
479
  #### Class template `filter_view` <a id="range.filter.view">[[range.filter.view]]</a>
 
483
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
484
  requires view<V> && is_object_v<Pred>
485
  class filter_view : public view_interface<filter_view<V, Pred>> {
486
  private:
487
  V base_ = V(); // exposition only
488
+ movable-box<Pred> pred_; // exposition only
489
 
490
  // [range.filter.iterator], class filter_view::iterator
491
  class iterator; // exposition only
492
+
493
  // [range.filter.sentinel], class filter_view::sentinel
494
  class sentinel; // exposition only
495
 
496
  public:
497
+ filter_view() requires default_initializable<V> && default_initializable<Pred> = default;
498
+ constexpr explicit filter_view(V base, Pred pred);
499
 
500
  constexpr V base() const & requires copy_constructible<V> { return base_; }
501
  constexpr V base() && { return std::move(base_); }
502
 
503
  constexpr const Pred& pred() const;
 
515
  filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
516
  }
517
  ```
518
 
519
  ``` cpp
520
+ constexpr explicit filter_view(V base, Pred pred);
521
  ```
522
 
523
  *Effects:* Initializes *base\_* with `std::move(base)` and initializes
524
  *pred\_* with `std::move(pred)`.
525
 
 
531
 
532
  ``` cpp
533
  constexpr iterator begin();
534
  ```
535
 
536
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
537
 
538
  *Returns:* `{*this, ranges::find_if(`*`base_`*`, ref(*`*`pred_`*`))}`.
539
 
540
  *Remarks:* In order to provide the amortized constant time complexity
541
  required by the `range` concept when `filter_view` models
 
550
  requires view<V> && is_object_v<Pred>
551
  class filter_view<V, Pred>::iterator {
552
  private:
553
  iterator_t<V> current_ = iterator_t<V>(); // exposition only
554
  filter_view* parent_ = nullptr; // exposition only
555
+
556
  public:
557
+ using iterator_concept = see belownc;
558
+ using iterator_category = see belownc; // not always present
559
  using value_type = range_value_t<V>;
560
  using difference_type = range_difference_t<V>;
561
 
562
+ iterator() requires default_initializable<iterator_t<V>> = default;
563
  constexpr iterator(filter_view& parent, iterator_t<V> current);
564
 
565
+ constexpr const iterator_t<V>& base() const & noexcept;
 
566
  constexpr iterator_t<V> base() &&;
567
  constexpr range_reference_t<V> operator*() const;
568
  constexpr iterator_t<V> operator->() const
569
  requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
570
 
 
578
  friend constexpr bool operator==(const iterator& x, const iterator& y)
579
  requires equality_comparable<iterator_t<V>>;
580
 
581
  friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
582
  noexcept(noexcept(ranges::iter_move(i.current_)));
583
+
584
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
585
  noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
586
  requires indirectly_swappable<iterator_t<V>>;
587
  };
588
  }
 
598
  `bidirectional_iterator_tag`.
599
  - Otherwise, if `V` models `forward_range`, then `iterator_concept`
600
  denotes `forward_iterator_tag`.
601
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
602
 
603
+ The member *typedef-name* `iterator_category` is defined if and only if
604
+ `V` models `forward_range`. In that case, `iterator::iterator_category`
605
+ is defined as follows:
606
 
607
  - Let `C` denote the type
608
  `iterator_traits<iterator_t<V>>::iterator_category`.
609
  - If `C` models `derived_from<bidirectional_iterator_tag>`, then
610
  `iterator_category` denotes `bidirectional_iterator_tag`.
 
618
 
619
  *Effects:* Initializes *current\_* with `std::move(current)` and
620
  *parent\_* with `addressof(parent)`.
621
 
622
  ``` cpp
623
+ constexpr const iterator_t<V>& base() const & noexcept;
 
624
  ```
625
 
626
  *Effects:* Equivalent to: `return `*`current_`*`;`
627
 
628
  ``` cpp
629
  constexpr iterator_t<V> base() &&;
630
  ```
631
 
632
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
633
 
634
  ``` cpp
635
  constexpr range_reference_t<V> operator*() const;
636
  ```
637
 
 
729
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
730
  requires view<V> && is_object_v<Pred>
731
  class filter_view<V, Pred>::sentinel {
732
  private:
733
  sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
734
+
735
  public:
736
  sentinel() = default;
737
  constexpr explicit sentinel(filter_view& parent);
738
 
739
  constexpr sentinel_t<V> base() const;
 
763
 
764
  ### Transform view <a id="range.transform">[[range.transform]]</a>
765
 
766
  #### Overview <a id="range.transform.overview">[[range.transform.overview]]</a>
767
 
768
+ `transform_view` presents a view of an underlying sequence after
769
  applying a transformation function to each element.
770
 
771
  The name `views::transform` denotes a range adaptor object
772
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
773
  expression `views::transform(E, F)` is expression-equivalent to
774
+ `transform_view(E, F)`.
775
 
776
  [*Example 1*:
777
 
778
  ``` cpp
779
  vector<int> is{ 0, 1, 2, 3, 4 };
780
+ auto squares = views::transform(is, [](int i) { return i * i; });
781
  for (int i : squares)
782
+ cout << i << ' '; // prints 0 1 4 9 16
783
  ```
784
 
785
  — *end example*]
786
 
787
  #### Class template `transform_view` <a id="range.transform.view">[[range.transform.view]]</a>
788
 
789
  ``` cpp
790
  namespace std::ranges {
791
+ template<input_range V, move_constructible F>
792
  requires view<V> && is_object_v<F> &&
793
  regular_invocable<F&, range_reference_t<V>> &&
794
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
795
  class transform_view : public view_interface<transform_view<V, F>> {
796
  private:
797
  // [range.transform.iterator], class template transform_view::iterator
798
  template<bool> struct iterator; // exposition only
799
+
800
  // [range.transform.sentinel], class template transform_view::sentinel
801
  template<bool> struct sentinel; // exposition only
802
 
803
  V base_ = V(); // exposition only
804
+ movable-box<F> fun_; // exposition only
805
 
806
  public:
807
+ transform_view() requires default_initializable<V> && default_initializable<F> = default;
808
+ constexpr explicit transform_view(V base, F fun);
809
 
810
  constexpr V base() const & requires copy_constructible<V> { return base_; }
811
  constexpr V base() && { return std::move(base_); }
812
 
813
  constexpr iterator<false> begin();
 
833
  transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
834
  }
835
  ```
836
 
837
  ``` cpp
838
+ constexpr explicit transform_view(V base, F fun);
839
  ```
840
 
841
  *Effects:* Initializes *base\_* with `std::move(base)` and *fun\_* with
842
  `std::move(fun)`.
843
 
 
909
 
910
  #### Class template `transform_view::iterator` <a id="range.transform.iterator">[[range.transform.iterator]]</a>
911
 
912
  ``` cpp
913
  namespace std::ranges {
914
+ template<input_range V, move_constructible F>
915
  requires view<V> && is_object_v<F> &&
916
  regular_invocable<F&, range_reference_t<V>> &&
917
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
918
  template<bool Const>
919
  class transform_view<V, F>::iterator {
920
  private:
921
+ using Parent = maybe-const<Const, transform_view>; // exposition only
922
+ using Base = maybe-const<Const, V>; // exposition only
923
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
 
 
 
924
  Parent* parent_ = nullptr; // exposition only
925
+
926
  public:
927
+ using iterator_concept = see belownc;
928
+ using iterator_category = see belownc; // not always present
929
  using value_type =
930
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>>;
931
  using difference_type = range_difference_t<Base>;
932
 
933
+ iterator() requires default_initializable<iterator_t<Base>> = default;
934
  constexpr iterator(Parent& parent, iterator_t<Base> current);
935
  constexpr iterator(iterator<!Const> i)
936
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
937
 
938
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
939
  constexpr iterator_t<Base> base() &&;
940
+
941
  constexpr decltype(auto) operator*() const
942
+ noexcept(noexcept(invoke(*parent_->fun_, *current_))) {
943
+ return invoke(*parent_->fun_, *current_);
944
+ }
945
 
946
  constexpr iterator& operator++();
947
  constexpr void operator++(int);
948
  constexpr iterator operator++(int) requires forward_range<Base>;
949
 
 
952
 
953
  constexpr iterator& operator+=(difference_type n)
954
  requires random_access_range<Base>;
955
  constexpr iterator& operator-=(difference_type n)
956
  requires random_access_range<Base>;
957
+
958
  constexpr decltype(auto) operator[](difference_type n) const
959
+ requires random_access_range<Base> {
960
+ return invoke(*parent_->fun_, current_[n]);
961
+ }
962
 
963
  friend constexpr bool operator==(const iterator& x, const iterator& y)
964
  requires equality_comparable<iterator_t<Base>>;
965
 
966
  friend constexpr bool operator<(const iterator& x, const iterator& y)
 
980
  requires random_access_range<Base>;
981
 
982
  friend constexpr iterator operator-(iterator i, difference_type n)
983
  requires random_access_range<Base>;
984
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
985
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
 
 
 
 
 
 
 
 
 
 
 
 
 
986
  };
987
  }
988
  ```
989
 
990
  `iterator::iterator_concept` is defined as follows:
991
 
992
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
993
+ denotes `random_access_iterator_tag`.
994
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
995
  `iterator_concept` denotes `bidirectional_iterator_tag`.
996
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
997
  denotes `forward_iterator_tag`.
998
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
999
 
1000
+ The member *typedef-name* `iterator_category` is defined if and only if
1001
+ *`Base`* models `forward_range`. In that case,
1002
  `iterator::iterator_category` is defined as follows: Let `C` denote the
1003
  type `iterator_traits<iterator_t<Base>>::iterator_category`.
1004
 
1005
  - If
1006
+ `is_reference_v<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>>`
1007
  is `true`, then
1008
  - if `C` models `derived_from<contiguous_iterator_tag>`,
1009
  `iterator_category` denotes `random_access_iterator_tag`;
1010
  - otherwise, `iterator_category` denotes `C`.
1011
  - Otherwise, `iterator_category` denotes `input_iterator_tag`.
 
1024
 
1025
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
1026
  and *parent\_* with `i.`*`parent_`*.
1027
 
1028
  ``` cpp
1029
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
1030
  ```
1031
 
1032
  *Effects:* Equivalent to: `return `*`current_`*`;`
1033
 
1034
  ``` cpp
1035
  constexpr iterator_t<Base> base() &&;
1036
  ```
1037
 
1038
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
1039
 
1040
  ``` cpp
1041
  constexpr iterator& operator++();
1042
  ```
1043
 
 
1050
 
1051
  ``` cpp
1052
  constexpr void operator++(int);
1053
  ```
1054
 
1055
+ *Effects:* Equivalent to `++`*`current_`*.
1056
 
1057
  ``` cpp
1058
  constexpr iterator operator++(int) requires forward_range<Base>;
1059
  ```
1060
 
 
1162
  friend constexpr iterator operator+(difference_type n, iterator i)
1163
  requires random_access_range<Base>;
1164
  ```
1165
 
1166
  *Effects:* Equivalent to:
1167
+ `return `*`iterator`*`{*i.`*`parent_`*`, i.`*`current_`*` + n};`
1168
 
1169
  ``` cpp
1170
  friend constexpr iterator operator-(iterator i, difference_type n)
1171
  requires random_access_range<Base>;
1172
  ```
1173
 
1174
  *Effects:* Equivalent to:
1175
+ `return `*`iterator`*`{*i.`*`parent_`*`, i.`*`current_`*` - n};`
1176
 
1177
  ``` cpp
1178
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
1179
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
1180
  ```
1181
 
1182
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
1183
 
 
 
 
 
 
 
 
 
 
1184
  #### Class template `transform_view::sentinel` <a id="range.transform.sentinel">[[range.transform.sentinel]]</a>
1185
 
1186
  ``` cpp
1187
  namespace std::ranges {
1188
+ template<input_range V, move_constructible F>
1189
  requires view<V> && is_object_v<F> &&
1190
  regular_invocable<F&, range_reference_t<V>> &&
1191
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
1192
  template<bool Const>
1193
  class transform_view<V, F>::sentinel {
1194
  private:
1195
+ using Parent = maybe-const<Const, transform_view>; // exposition only
1196
+ using Base = maybe-const<Const, V>; // exposition only
 
1197
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1198
+
1199
  public:
1200
  sentinel() = default;
1201
  constexpr explicit sentinel(sentinel_t<Base> end);
1202
  constexpr sentinel(sentinel<!Const> i)
1203
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1204
 
1205
  constexpr sentinel_t<Base> base() const;
1206
 
1207
+ template<bool OtherConst>
1208
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1209
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
1210
 
1211
+ template<bool OtherConst>
1212
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1213
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
1214
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
1215
+
1216
+ template<bool OtherConst>
1217
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1218
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
1219
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
1220
  };
1221
  }
1222
  ```
1223
 
1224
  ``` cpp
 
1239
  ```
1240
 
1241
  *Effects:* Equivalent to: `return `*`end_`*`;`
1242
 
1243
  ``` cpp
1244
+ template<bool OtherConst>
1245
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1246
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
1247
  ```
1248
 
1249
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
1250
 
1251
  ``` cpp
1252
+ template<bool OtherConst>
1253
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1254
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
1255
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
1256
  ```
1257
 
1258
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
1259
 
1260
  ``` cpp
1261
+ template<bool OtherConst>
1262
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1263
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
1264
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
1265
  ```
1266
 
1267
  *Effects:* Equivalent to: `return y.`*`end_`*` - x.`*`current_`*`;`
1268
 
1269
  ### Take view <a id="range.take">[[range.take]]</a>
1270
 
1271
  #### Overview <a id="range.take.overview">[[range.take.overview]]</a>
1272
 
1273
+ `take_view` produces a view of the first N elements from another view,
1274
+ or all the elements if the adapted view contains fewer than N.
1275
 
1276
  The name `views::take` denotes a range adaptor object
1277
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
1278
  `remove_cvref_t<decltype((E))>`, and let `D` be
1279
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
1280
  `convertible_to<D>`, `views::take(E, F)` is ill-formed. Otherwise, the
1281
  expression `views::take(E, F)` is expression-equivalent to:
1282
 
1283
+ - If `T` is a specialization of `empty_view` [[range.empty.view]], then
1284
+ `((void)F, decay-copy(E))`, except that the evaluations of `E` and `F`
1285
+ are indeterminately sequenced.
1286
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
1287
+ is a specialization of `span` [[views.span]], `basic_string_view`
1288
+ [[string.view]], or `subrange` [[range.subrange]], then
1289
+ `U(ranges::begin(E),
1290
+ ranges::begin(E) + std::min<D>(ranges::distance(E), F))`, except that
1291
+ `E` is evaluated only once, where `U` is a type determined as follows:
1292
+ - if `T` is a specialization of `span`, then `U` is
1293
+ `span<typename T::element_type>`;
1294
+ - otherwise, if `T` is a specialization of `basic_string_view`, then
1295
+ `U` is `T`;
1296
+ - otherwise, `T` is a specialization of `subrange`, and `U` is
1297
+ `subrange<iterator_t<T>>`;
1298
+ - otherwise, if `T` is a specialization of `iota_view`
1299
+ [[range.iota.view]] that models `random_access_range` and
1300
+ `sized_range`, then `iota_view(*ranges::begin(E),
1301
+ *(ranges::begin(E) + std::{}min<D>(ranges::distance(E), F)))`, except
1302
+ that `E` is evaluated only once.
1303
+ - Otherwise, if `T` is a specialization of `repeat_view`
1304
+ [[range.repeat.view]]:
1305
+ - if `T` models `sized_range`, then
1306
+ ``` cpp
1307
+ views::repeat(*E.value_, std::min<D>(ranges::distance(E), F))
1308
+ ```
1309
 
1310
+ except that `E` is evaluated only once;
1311
+ - otherwise, `views::repeat(*E.value_, static_cast<D>(F))`.
1312
+ - Otherwise, `take_view(E, F)`.
 
1313
 
1314
  [*Example 1*:
1315
 
1316
  ``` cpp
1317
  vector<int> is{0,1,2,3,4,5,6,7,8,9};
1318
+ for (int i : is | views::take(5))
1319
+ cout << i << ' '; // prints 0 1 2 3 4
 
1320
  ```
1321
 
1322
  — *end example*]
1323
 
1324
  #### Class template `take_view` <a id="range.take.view">[[range.take.view]]</a>
 
1328
  template<view V>
1329
  class take_view : public view_interface<take_view<V>> {
1330
  private:
1331
  V base_ = V(); // exposition only
1332
  range_difference_t<V> count_ = 0; // exposition only
1333
+
1334
  // [range.take.sentinel], class template take_view::sentinel
1335
+ template<bool> class sentinel; // exposition only
1336
+
1337
  public:
1338
+ take_view() requires default_initializable<V> = default;
1339
+ constexpr explicit take_view(V base, range_difference_t<V> count);
1340
 
1341
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1342
  constexpr V base() && { return std::move(base_); }
1343
 
1344
  constexpr auto begin() requires (!simple-view<V>) {
1345
  if constexpr (sized_range<V>) {
1346
+ if constexpr (random_access_range<V>) {
1347
  return ranges::begin(base_);
1348
+ } else {
1349
+ auto sz = range_difference_t<V>(size());
1350
+ return counted_iterator(ranges::begin(base_), sz);
1351
+ }
1352
+ } else if constexpr (sized_sentinel_for<sentinel_t<V>, iterator_t<V>>) {
1353
+ auto it = ranges::begin(base_);
1354
+ auto sz = std::min(count_, ranges::end(base_) - it);
1355
+ return counted_iterator(std::move(it), sz);
1356
+ } else {
1357
+ return counted_iterator(ranges::begin(base_), count_);
1358
  }
 
 
1359
  }
1360
 
1361
  constexpr auto begin() const requires range<const V> {
1362
  if constexpr (sized_range<const V>) {
1363
+ if constexpr (random_access_range<const V>) {
1364
  return ranges::begin(base_);
1365
+ } else {
1366
+ auto sz = range_difference_t<const V>(size());
1367
+ return counted_iterator(ranges::begin(base_), sz);
1368
+ }
1369
+ } else if constexpr (sized_sentinel_for<sentinel_t<const V>, iterator_t<const V>>) {
1370
+ auto it = ranges::begin(base_);
1371
+ auto sz = std::min(count_, ranges::end(base_) - it);
1372
+ return counted_iterator(std::move(it), sz);
1373
+ } else {
1374
+ return counted_iterator(ranges::begin(base_), count_);
1375
  }
 
 
1376
  }
1377
 
1378
  constexpr auto end() requires (!simple-view<V>) {
1379
  if constexpr (sized_range<V>) {
1380
  if constexpr (random_access_range<V>)
1381
+ return ranges::begin(base_) + range_difference_t<V>(size());
1382
  else
1383
  return default_sentinel;
1384
+ } else if constexpr (sized_sentinel_for<sentinel_t<V>, iterator_t<V>>) {
1385
+ return default_sentinel;
1386
+ } else {
1387
  return sentinel<false>{ranges::end(base_)};
1388
  }
1389
+ }
1390
 
1391
  constexpr auto end() const requires range<const V> {
1392
  if constexpr (sized_range<const V>) {
1393
  if constexpr (random_access_range<const V>)
1394
+ return ranges::begin(base_) + range_difference_t<const V>(size());
1395
  else
1396
  return default_sentinel;
1397
+ } else if constexpr (sized_sentinel_for<sentinel_t<const V>, iterator_t<const V>>) {
1398
+ return default_sentinel;
1399
+ } else {
1400
  return sentinel<true>{ranges::end(base_)};
1401
  }
1402
+ }
1403
 
1404
  constexpr auto size() requires sized_range<V> {
1405
  auto n = ranges::size(base_);
1406
  return ranges::min(n, static_cast<decltype(n)>(count_));
1407
  }
 
1410
  auto n = ranges::size(base_);
1411
  return ranges::min(n, static_cast<decltype(n)>(count_));
1412
  }
1413
  };
1414
 
1415
+ template<class R>
1416
  take_view(R&&, range_difference_t<R>)
1417
  -> take_view<views::all_t<R>>;
1418
  }
1419
  ```
1420
 
1421
  ``` cpp
1422
+ constexpr explicit take_view(V base, range_difference_t<V> count);
1423
  ```
1424
 
1425
+ *Preconditions:* `count >= 0` is `true`.
1426
+
1427
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
1428
  with `count`.
1429
 
1430
  #### Class template `take_view::sentinel` <a id="range.take.sentinel">[[range.take.sentinel]]</a>
1431
 
 
1433
  namespace std::ranges {
1434
  template<view V>
1435
  template<bool Const>
1436
  class take_view<V>::sentinel {
1437
  private:
1438
+ using Base = maybe-const<Const, V>; // exposition only
1439
+ template<bool OtherConst>
1440
+ using CI = counted_iterator<iterator_t<maybe-const<OtherConst, V>>>; // exposition only
1441
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1442
+
1443
  public:
1444
  sentinel() = default;
1445
  constexpr explicit sentinel(sentinel_t<Base> end);
1446
  constexpr sentinel(sentinel<!Const> s)
1447
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1448
 
1449
  constexpr sentinel_t<Base> base() const;
1450
 
1451
+ friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
1452
+
1453
+ template<bool OtherConst = !Const>
1454
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1455
+ friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
1456
  };
1457
  }
1458
  ```
1459
 
1460
  ``` cpp
 
1475
  ```
1476
 
1477
  *Effects:* Equivalent to: `return `*`end_`*`;`
1478
 
1479
  ``` cpp
1480
+ friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
1481
+
1482
+ template<bool OtherConst = !Const>
1483
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1484
+ friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
1485
  ```
1486
 
1487
  *Effects:* Equivalent to:
1488
  `return y.count() == 0 || y.base() == x.`*`end_`*`;`
1489
 
1490
  ### Take while view <a id="range.take.while">[[range.take.while]]</a>
1491
 
1492
  #### Overview <a id="range.take.while.overview">[[range.take.while.overview]]</a>
1493
 
1494
+ Given a unary predicate `pred` and a view `r`, `take_while_view`
1495
+ produces a view of the range \[`ranges::begin(r)`,
1496
  `ranges::find_if_not(r, pred)`).
1497
 
1498
  The name `views::take_while` denotes a range adaptor object
1499
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1500
  expression `views::take_while(E, F)` is expression-equivalent to
1501
+ `take_while_view(E, F)`.
1502
 
1503
  [*Example 1*:
1504
 
1505
  ``` cpp
1506
  auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
1507
  auto small = [](const auto x) noexcept { return x < 5; };
1508
+ auto small_ints = views::istream<int>(input) | views::take_while(small);
1509
  for (const auto i : small_ints) {
1510
  cout << i << ' '; // prints 0 1 2 3 4
1511
  }
1512
  auto i = 0;
1513
  input >> i;
 
1526
  class take_while_view : public view_interface<take_while_view<V, Pred>> {
1527
  // [range.take.while.sentinel], class template take_while_view::sentinel
1528
  template<bool> class sentinel; // exposition only
1529
 
1530
  V base_ = V(); // exposition only
1531
+ movable-box<Pred> pred_; // exposition only
1532
 
1533
  public:
1534
+ take_while_view() requires default_initializable<V> && default_initializable<Pred> = default;
1535
+ constexpr explicit take_while_view(V base, Pred pred);
1536
 
1537
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1538
  constexpr V base() && { return std::move(base_); }
1539
 
1540
  constexpr const Pred& pred() const;
1541
 
1542
  constexpr auto begin() requires (!simple-view<V>)
1543
  { return ranges::begin(base_); }
1544
 
1545
+ constexpr auto begin() const
1546
+ requires range<const V> &&
1547
+ indirect_unary_predicate<const Pred, iterator_t<const V>>
1548
  { return ranges::begin(base_); }
1549
 
1550
  constexpr auto end() requires (!simple-view<V>)
1551
  { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
1552
 
1553
+ constexpr auto end() const
1554
+ requires range<const V> &&
1555
+ indirect_unary_predicate<const Pred, iterator_t<const V>>
1556
  { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
1557
  };
1558
 
1559
  template<class R, class Pred>
1560
  take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
1561
  }
1562
  ```
1563
 
1564
  ``` cpp
1565
+ constexpr explicit take_while_view(V base, Pred pred);
1566
  ```
1567
 
1568
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
1569
  `std::move(pred)`.
1570
 
 
1580
  namespace std::ranges {
1581
  template<view V, class Pred>
1582
  requires input_range<V> && is_object_v<Pred> &&
1583
  indirect_unary_predicate<const Pred, iterator_t<V>>
1584
  template<bool Const>
1585
+ class take_while_view<V, Pred>::sentinel {
1586
+ using Base = maybe-const<Const, V>; // exposition only
1587
 
1588
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
1589
  const Pred* pred_ = nullptr; // exposition only
1590
+
1591
  public:
1592
  sentinel() = default;
1593
  constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
1594
  constexpr sentinel(sentinel<!Const> s)
1595
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1596
 
1597
  constexpr sentinel_t<Base> base() const { return end_; }
1598
 
1599
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
1600
+
1601
+ template<bool OtherConst = !Const>
1602
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1603
+ friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x,
1604
+ const sentinel& y);
1605
  };
1606
  }
1607
  ```
1608
 
1609
  ``` cpp
 
1615
  ``` cpp
1616
  constexpr sentinel(sentinel<!Const> s)
1617
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
1618
  ```
1619
 
1620
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)` and
1621
+ *pred\_* with `s.`*`pred_`*.
1622
 
1623
  ``` cpp
1624
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
1625
+
1626
+ template<bool OtherConst = !Const>
1627
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1628
+ friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x,
1629
+ const sentinel& y);
1630
  ```
1631
 
1632
  *Effects:* Equivalent to:
1633
  `return y.`*`end_`*` == x || !invoke(*y.`*`pred_`*`, *x);`
1634
 
1635
  ### Drop view <a id="range.drop">[[range.drop]]</a>
1636
 
1637
  #### Overview <a id="range.drop.overview">[[range.drop.overview]]</a>
1638
 
1639
+ `drop_view` produces a view excluding the first N elements from another
1640
+ view, or an empty range if the adapted view contains fewer than N
1641
+ elements.
1642
 
1643
  The name `views::drop` denotes a range adaptor object
1644
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
1645
  `remove_cvref_t<decltype((E))>`, and let `D` be
1646
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
1647
  `convertible_to<D>`, `views::drop(E, F)` is ill-formed. Otherwise, the
1648
  expression `views::drop(E, F)` is expression-equivalent to:
1649
 
1650
+ - If `T` is a specialization of `empty_view` [[range.empty.view]], then
1651
+ `((void)F, decay-copy(E))`, except that the evaluations of `E` and `F`
1652
+ are indeterminately sequenced.
1653
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
1654
  is
1655
+ - a specialization of `span` [[views.span]],
 
1656
  - a specialization of `basic_string_view` [[string.view]],
1657
+ - a specialization of `iota_view` [[range.iota.view]], or
1658
+ - a specialization of `subrange` [[range.subrange]] where
1659
+ `T::StoreSize` is `false`,
1660
 
1661
  then
1662
+ `U(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::end(E))`,
1663
+ except that `E` is evaluated only once, where `U` is
1664
+ `span<typename T::element_type>` if `T` is a specialization of `span`
1665
+ and `T` otherwise.
1666
+ - Otherwise, if `T` is a specialization of `subrange` [[range.subrange]]
1667
+ that models `random_access_range` and `sized_range`, then
1668
+ `T(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::{}end(E),
1669
+ to-unsigned-like(ranges::distance(E) -
1670
+ std::min<D>(ranges::distance(E), F)))`, except that `E` and `F` are
1671
+ each evaluated only once.
1672
+ - Otherwise, if `T` is a specialization of `repeat_view`
1673
+ [[range.repeat.view]]:
1674
+ - if `T` models `sized_range`, then
1675
+ ``` cpp
1676
+ views::repeat(*E.value_, ranges::distance(E) - std::min<D>(ranges::distance(E), F))
1677
+ ```
1678
+
1679
+ except that `E` is evaluated only once;
1680
+ - otherwise, `((void)F, decay-copy(E))`, except that the evaluations
1681
+ of `E` and `F` are indeterminately sequenced.
1682
+ - Otherwise, `drop_view(E, F)`.
1683
 
1684
  [*Example 1*:
1685
 
1686
  ``` cpp
1687
  auto ints = views::iota(0) | views::take(10);
1688
+ for (auto i : ints | views::drop(5)) {
 
1689
  cout << i << ' '; // prints 5 6 7 8 9
1690
  }
1691
  ```
1692
 
1693
  — *end example*]
 
1697
  ``` cpp
1698
  namespace std::ranges {
1699
  template<view V>
1700
  class drop_view : public view_interface<drop_view<V>> {
1701
  public:
1702
+ drop_view() requires default_initializable<V> = default;
1703
+ constexpr explicit drop_view(V base, range_difference_t<V> count);
1704
 
1705
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1706
  constexpr V base() && { return std::move(base_); }
1707
 
1708
  constexpr auto begin()
1709
+ requires (!(simple-view<V> &&
1710
+ random_access_range<const V> && sized_range<const V>));
1711
  constexpr auto begin() const
1712
+ requires random_access_range<const V> && sized_range<const V>;
1713
 
1714
+ constexpr auto end() requires (!simple-view<V>)
 
1715
  { return ranges::end(base_); }
1716
 
1717
+ constexpr auto end() const requires range<const V>
 
1718
  { return ranges::end(base_); }
1719
 
1720
+ constexpr auto size() requires sized_range<V> {
 
 
1721
  const auto s = ranges::size(base_);
1722
  const auto c = static_cast<decltype(s)>(count_);
1723
  return s < c ? 0 : s - c;
1724
  }
1725
 
1726
+ constexpr auto size() const requires sized_range<const V> {
 
 
1727
  const auto s = ranges::size(base_);
1728
  const auto c = static_cast<decltype(s)>(count_);
1729
  return s < c ? 0 : s - c;
1730
  }
1731
+
1732
  private:
1733
  V base_ = V(); // exposition only
1734
  range_difference_t<V> count_ = 0; // exposition only
1735
  };
1736
 
 
1738
  drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
1739
  }
1740
  ```
1741
 
1742
  ``` cpp
1743
+ constexpr explicit drop_view(V base, range_difference_t<V> count);
1744
  ```
1745
 
1746
  *Preconditions:* `count >= 0` is `true`.
1747
 
1748
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
1749
  with `count`.
1750
 
1751
  ``` cpp
1752
  constexpr auto begin()
1753
+ requires (!(simple-view<V> &&
1754
+ random_access_range<const V> && sized_range<const V>));
1755
  constexpr auto begin() const
1756
+ requires random_access_range<const V> && sized_range<const V>;
1757
  ```
1758
 
1759
  *Returns:*
1760
+ `ranges::next(ranges::begin(`*`base_`*`), `*`count_`*`, ranges::end(`*`base_`*`))`.
1761
 
1762
  *Remarks:* In order to provide the amortized constant-time complexity
1763
  required by the `range` concept when `drop_view` models `forward_range`,
1764
  the first overload caches the result within the `drop_view` for use on
1765
  subsequent calls.
 
1769
 
1770
  ### Drop while view <a id="range.drop.while">[[range.drop.while]]</a>
1771
 
1772
  #### Overview <a id="range.drop.while.overview">[[range.drop.while.overview]]</a>
1773
 
1774
+ Given a unary predicate `pred` and a view `r`, `drop_while_view`
1775
+ produces a view of the range \[`ranges::find_if_not(r, pred)`,
1776
  `ranges::end(r)`).
1777
 
1778
  The name `views::drop_while` denotes a range adaptor object
1779
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
1780
  expression `views::drop_while(E, F)` is expression-equivalent to
1781
+ `drop_while_view(E, F)`.
1782
 
1783
  [*Example 1*:
1784
 
1785
  ``` cpp
1786
+ constexpr auto source = " \t \t \t hello there"sv;
1787
  auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
1788
+ auto skip_ws = views::drop_while(source, is_invisible);
1789
  for (auto c : skip_ws) {
1790
  cout << c; // prints hello there with no leading space
1791
  }
1792
  ```
1793
 
 
1800
  template<view V, class Pred>
1801
  requires input_range<V> && is_object_v<Pred> &&
1802
  indirect_unary_predicate<const Pred, iterator_t<V>>
1803
  class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
1804
  public:
1805
+ drop_while_view() requires default_initializable<V> && default_initializable<Pred> = default;
1806
+ constexpr explicit drop_while_view(V base, Pred pred);
1807
 
1808
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1809
  constexpr V base() && { return std::move(base_); }
1810
 
1811
  constexpr const Pred& pred() const;
1812
 
1813
  constexpr auto begin();
1814
 
1815
+ constexpr auto end() { return ranges::end(base_); }
 
1816
 
1817
  private:
1818
  V base_ = V(); // exposition only
1819
+ movable-box<Pred> pred_; // exposition only
1820
  };
1821
 
1822
  template<class R, class Pred>
1823
  drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
1824
  }
1825
  ```
1826
 
1827
  ``` cpp
1828
+ constexpr explicit drop_while_view(V base, Pred pred);
1829
  ```
1830
 
1831
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
1832
  `std::move(pred)`.
1833
 
 
1839
 
1840
  ``` cpp
1841
  constexpr auto begin();
1842
  ```
1843
 
1844
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
1845
+
1846
+ *Returns:* `ranges::find_if_not(`*`base_`*`, cref(*`*`pred_`*`))`.
1847
 
1848
  *Remarks:* In order to provide the amortized constant-time complexity
1849
  required by the `range` concept when `drop_while_view` models
1850
  `forward_range`, the first call caches the result within the
1851
  `drop_while_view` for use on subsequent calls.
 
1856
 
1857
  ### Join view <a id="range.join">[[range.join]]</a>
1858
 
1859
  #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
1860
 
1861
+ `join_view` flattens a view of ranges into a view.
1862
 
1863
  The name `views::join` denotes a range adaptor object
1864
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
1865
+ `views::join(E)` is expression-equivalent to
1866
+ `join_view<views::all_t<decltype((E))>>{E}`.
1867
 
1868
  [*Example 1*:
1869
 
1870
  ``` cpp
1871
  vector<string> ss{"hello", " ", "world", "!"};
1872
+ for (char ch : ss | views::join)
1873
+ cout << ch; // prints hello world!
 
1874
  ```
1875
 
1876
  — *end example*]
1877
 
1878
  #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
1879
 
1880
  ``` cpp
1881
  namespace std::ranges {
1882
  template<input_range V>
1883
+ requires view<V> && input_range<range_reference_t<V>>
 
 
1884
  class join_view : public view_interface<join_view<V>> {
1885
  private:
1886
+ using InnerRng = range_reference_t<V>; // exposition only
1887
+
1888
  // [range.join.iterator], class template join_view::iterator
1889
  template<bool Const>
1890
  struct iterator; // exposition only
1891
+
1892
  // [range.join.sentinel], class template join_view::sentinel
1893
  template<bool Const>
1894
  struct sentinel; // exposition only
1895
 
1896
  V base_ = V(); // exposition only
1897
+
1898
+ non-propagating-cache<iterator_t<V>> outer_; // exposition only, present only
1899
+ // when !forward_range<V>
1900
+ non-propagating-cache<remove_cv_t<InnerRng>> inner_; // exposition only, present only
1901
+ // if is_reference_v<InnerRng> is false
1902
+
1903
  public:
1904
+ join_view() requires default_initializable<V> = default;
1905
  constexpr explicit join_view(V base);
1906
 
1907
  constexpr V base() const & requires copy_constructible<V> { return base_; }
1908
  constexpr V base() && { return std::move(base_); }
1909
 
1910
  constexpr auto begin() {
1911
+ if constexpr (forward_range<V>) {
1912
  constexpr bool use_const = simple-view<V> &&
1913
+ is_reference_v<InnerRng>;
1914
  return iterator<use_const>{*this, ranges::begin(base_)};
1915
+ } else {
1916
+ outer_ = ranges::begin(base_);
1917
+ return iterator<false>{*this};
1918
+ }
1919
  }
1920
 
1921
  constexpr auto begin() const
1922
+ requires forward_range<const V> &&
1923
+ is_reference_v<range_reference_t<const V>> &&
1924
+ input_range<range_reference_t<const V>>
1925
+ { return iterator<true>{*this, ranges::begin(base_)}; }
1926
 
1927
  constexpr auto end() {
1928
  if constexpr (forward_range<V> &&
1929
  is_reference_v<InnerRng> && forward_range<InnerRng> &&
1930
  common_range<V> && common_range<InnerRng>)
 
1932
  else
1933
  return sentinel<simple-view<V>>{*this};
1934
  }
1935
 
1936
  constexpr auto end() const
1937
+ requires forward_range<const V> &&
 
 
1938
  is_reference_v<range_reference_t<const V>> &&
1939
+ input_range<range_reference_t<const V>> {
1940
+ if constexpr (forward_range<range_reference_t<const V>> &&
1941
  common_range<const V> &&
1942
  common_range<range_reference_t<const V>>)
1943
  return iterator<true>{*this, ranges::end(base_)};
1944
  else
1945
  return sentinel<true>{*this};
 
1960
  #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
1961
 
1962
  ``` cpp
1963
  namespace std::ranges {
1964
  template<input_range V>
1965
+ requires view<V> && input_range<range_reference_t<V>>
 
 
1966
  template<bool Const>
1967
  struct join_view<V>::iterator {
1968
  private:
1969
+ using Parent = maybe-const<Const, join_view>; // exposition only
1970
+ using Base = maybe-const<Const, V>; // exposition only
1971
+ using OuterIter = iterator_t<Base>; // exposition only
1972
+ using InnerIter = iterator_t<range_reference_t<Base>>; // exposition only
1973
 
1974
  static constexpr bool ref-is-glvalue = // exposition only
1975
  is_reference_v<range_reference_t<Base>>;
1976
 
1977
+ OuterIter outer_ = OuterIter(); // exposition only, present only
1978
+ // if Base models forward_range
1979
+ optional<InnerIter> inner_; // exposition only
1980
  Parent* parent_ = nullptr; // exposition only
1981
 
1982
  constexpr void satisfy(); // exposition only
1983
+
1984
+ constexpr OuterIter& outer(); // exposition only
1985
+ constexpr const OuterIter& outer() const; // exposition only
1986
+
1987
+ constexpr iterator(Parent& parent, OuterIter outer)
1988
+ requires forward_range<Base>; // exposition only
1989
+ constexpr explicit iterator(Parent& parent)
1990
+ requires (!forward_range<Base>); // exposition only
1991
+
1992
  public:
1993
  using iterator_concept = see below;
1994
+ using iterator_category = see below; // not always present
1995
  using value_type = range_value_t<range_reference_t<Base>>;
1996
  using difference_type = see below;
1997
 
1998
  iterator() = default;
 
1999
  constexpr iterator(iterator<!Const> i)
2000
  requires Const &&
2001
+ convertible_to<iterator_t<V>, OuterIter> &&
2002
+ convertible_to<iterator_t<InnerRng>, InnerIter>;
 
2003
 
2004
+ constexpr decltype(auto) operator*() const { return **inner_; }
2005
 
2006
+ constexpr InnerIter operator->() const
2007
+ requires has-arrow<InnerIter> && copyable<InnerIter>;
2008
 
2009
  constexpr iterator& operator++();
2010
  constexpr void operator++(int);
2011
  constexpr iterator operator++(int)
2012
  requires ref-is-glvalue && forward_range<Base> &&
 
2021
  requires ref-is-glvalue && bidirectional_range<Base> &&
2022
  bidirectional_range<range_reference_t<Base>> &&
2023
  common_range<range_reference_t<Base>>;
2024
 
2025
  friend constexpr bool operator==(const iterator& x, const iterator& y)
2026
+ requires ref-is-glvalue && forward_range<Base> &&
2027
  equality_comparable<iterator_t<range_reference_t<Base>>>;
2028
 
2029
  friend constexpr decltype(auto) iter_move(const iterator& i)
2030
+ noexcept(noexcept(ranges::iter_move(*i.inner_))) {
2031
+ return ranges::iter_move(*i.inner_);
2032
  }
2033
 
2034
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
2035
+ noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
2036
+ requires indirectly_swappable<InnerIter>;
2037
  };
2038
  }
2039
  ```
2040
 
2041
  `iterator::iterator_concept` is defined as follows:
2042
 
2043
+ - If *`ref-is-glvalue`* is `true`, *`Base`* models
2044
+ `bidirectional_range`, and `range_reference_t<Base>` models both
2045
+ `bidirectional_range` and `common_range`, then `iterator_concept`
2046
+ denotes `bidirectional_iterator_tag`.
2047
  - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
2048
  `range_reference_t<Base>` each model , then `iterator_concept` denotes
2049
  `forward_iterator_tag`.
2050
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
2051
 
2052
+ The member *typedef-name* `iterator_category` is defined if and only if
2053
+ *`ref-is-glvalue`* is `true`, *`Base`* models `forward_range`, and
2054
+ `range_reference_t<Base>` models `forward_range`. In that case,
2055
  `iterator::iterator_category` is defined as follows:
2056
 
2057
  - Let *OUTERC* denote
2058
  `iterator_traits<iterator_t<Base>>::iterator_category`, and let
2059
  *INNERC* denote
2060
  `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
2061
+ - If *OUTERC* and *INNERC* each model
2062
+ `derived_from<bidirectional_iterator_tag>` and
2063
+ `range_reference_t<Base>` models `common_range`, `iterator_category`
2064
  denotes `bidirectional_iterator_tag`.
 
 
 
2065
  - Otherwise, if *OUTERC* and *INNERC* each model
2066
+ `derived_from<forward_iterator_tag>`, `iterator_category` denotes
2067
+ `forward_iterator_tag`.
2068
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
2069
 
2070
  `iterator::difference_type` denotes the type:
2071
 
2072
  ``` cpp
2073
  common_type_t<
 
2077
 
2078
  `join_view` iterators use the *`satisfy`* function to skip over empty
2079
  inner ranges.
2080
 
2081
  ``` cpp
2082
+ constexpr OuterIter& outer();
2083
+ constexpr const OuterIter& outer() const;
2084
+ ```
2085
+
2086
+ *Returns:* *outer\_* if *Base* models `forward_range`; otherwise,
2087
+ `*`*`parent_`*`->`*`outer_`*.
2088
+
2089
+ ``` cpp
2090
+ constexpr void satisfy();
2091
  ```
2092
 
2093
  *Effects:* Equivalent to:
2094
 
2095
  ``` cpp
2096
+ auto update_inner = [this](const iterator_t<Base>& x) -> auto&& {
2097
+ if constexpr (ref-is-glvalue) // *x is a reference
2098
+ return *x;
2099
  else
2100
+ return parent_->inner_.emplace-deref(x);
2101
  };
2102
 
2103
+ for (; outer() != ranges::end(parent_->base_); ++outer()) {
2104
+ auto&& inner = update_inner(outer());
2105
  inner_ = ranges::begin(inner);
2106
+ if (*inner_ != ranges::end(inner))
2107
  return;
2108
  }
2109
  if constexpr (ref-is-glvalue)
2110
+ inner_.reset();
2111
  ```
2112
 
2113
  ``` cpp
2114
+ constexpr iterator(Parent& parent, OuterIter outer)
2115
+ requires forward_range<Base>;
2116
  ```
2117
 
2118
  *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
2119
  with `addressof(parent)`; then calls *`satisfy`*`()`.
2120
 
2121
+ ``` cpp
2122
+ constexpr explicit iterator(Parent& parent)
2123
+ requires (!forward_range<Base>);
2124
+ ```
2125
+
2126
+ *Effects:* Initializes *parent\_* with `addressof(parent)`; then calls
2127
+ *`satisfy`*`()`.
2128
+
2129
  ``` cpp
2130
  constexpr iterator(iterator<!Const> i)
2131
  requires Const &&
2132
+ convertible_to<iterator_t<V>, OuterIter> &&
2133
+ convertible_to<iterator_t<InnerRng>, InnerIter>;
 
2134
  ```
2135
 
2136
  *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
2137
  *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
2138
  `i.`*`parent_`*.
2139
 
2140
+ [*Note 1*: `Const` can only be `true` when *Base* models
2141
+ `forward_range`. — *end note*]
2142
+
2143
  ``` cpp
2144
+ constexpr InnerIter operator->() const
2145
+ requires has-arrow<InnerIter> && copyable<InnerIter>;
2146
  ```
2147
 
2148
+ *Effects:* Equivalent to: `return *`*`inner_`*`;`
2149
 
2150
  ``` cpp
2151
  constexpr iterator& operator++();
2152
  ```
2153
 
2154
  Let *`inner-range`* be:
2155
 
2156
+ - If *ref-is-glvalue* is `true`, `*`*`outer`*`()`.
2157
+ - Otherwise, `*`*`parent_`*`->`*`inner_`*.
2158
 
2159
  *Effects:* Equivalent to:
2160
 
2161
  ``` cpp
2162
+ if (++*inner_ == ranges::end(as-lvalue(inner-range))) {
2163
+ ++outer();
 
2164
  satisfy();
2165
  }
2166
  return *this;
2167
  ```
2168
 
 
2195
 
2196
  *Effects:* Equivalent to:
2197
 
2198
  ``` cpp
2199
  if (outer_ == ranges::end(parent_->base_))
2200
+ inner_ = ranges::end(as-lvalue(*--outer_));
2201
+ while (*inner_ == ranges::begin(as-lvalue(*outer_)))
2202
+ *inner_ = ranges::end(as-lvalue(*--outer_));
2203
+ --*inner_;
2204
  return *this;
2205
  ```
2206
 
2207
  ``` cpp
2208
  constexpr iterator operator--(int)
 
2219
  return tmp;
2220
  ```
2221
 
2222
  ``` cpp
2223
  friend constexpr bool operator==(const iterator& x, const iterator& y)
2224
+ requires ref-is-glvalue && forward_range<Base> &&
2225
  equality_comparable<iterator_t<range_reference_t<Base>>>;
2226
  ```
2227
 
2228
  *Effects:* Equivalent to:
2229
  `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
2230
 
2231
  ``` cpp
2232
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
2233
+ noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
2234
+ requires indirectly_swappable<InnerIter>;
2235
  ```
2236
 
2237
  *Effects:* Equivalent to:
2238
+ `return ranges::iter_swap(*x.`*`inner_`*`, *y.`*`inner_`*`);`
2239
 
2240
  #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
2241
 
2242
  ``` cpp
2243
  namespace std::ranges {
2244
  template<input_range V>
2245
+ requires view<V> && input_range<range_reference_t<V>>
 
 
2246
  template<bool Const>
2247
  struct join_view<V>::sentinel {
2248
  private:
2249
+ using Parent = maybe-const<Const, join_view>; // exposition only
2250
+ using Base = maybe-const<Const, V>; // exposition only
 
2251
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
2252
+
2253
  public:
2254
  sentinel() = default;
2255
 
2256
  constexpr explicit sentinel(Parent& parent);
2257
  constexpr sentinel(sentinel<!Const> s)
2258
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
2259
 
2260
+ template<bool OtherConst>
2261
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
2262
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
2263
+ };
2264
+ }
2265
+ ```
2266
+
2267
+ ``` cpp
2268
+ constexpr explicit sentinel(Parent& parent);
2269
+ ```
2270
+
2271
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
2272
+
2273
+ ``` cpp
2274
+ constexpr sentinel(sentinel<!Const> s)
2275
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
2276
+ ```
2277
+
2278
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
2279
+
2280
+ ``` cpp
2281
+ template<bool OtherConst>
2282
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
2283
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
2284
+ ```
2285
+
2286
+ *Effects:* Equivalent to: `return x.`*`outer`*`() == y.`*`end_`*`;`
2287
+
2288
+ ### Join with view <a id="range.join.with">[[range.join.with]]</a>
2289
+
2290
+ #### Overview <a id="range.join.with.overview">[[range.join.with.overview]]</a>
2291
+
2292
+ `join_with_view` takes a view and a delimiter, and flattens the view,
2293
+ inserting every element of the delimiter in between elements of the
2294
+ view. The delimiter can be a single element or a view of elements.
2295
+
2296
+ The name `views::join_with` denotes a range adaptor object
2297
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
2298
+ expression `views::join_with(E, F)` is expression-equivalent to
2299
+ `join_with_view(E, F)`.
2300
+
2301
+ [*Example 1*:
2302
+
2303
+ ``` cpp
2304
+ vector<string> vs = {"the", "quick", "brown", "fox"};
2305
+ for (char c : vs | views::join_with('-')) {
2306
+ cout << c;
2307
+ }
2308
+ // The above prints the-quick-brown-fox
2309
+ ```
2310
+
2311
+ — *end example*]
2312
+
2313
+ #### Class template `join_with_view` <a id="range.join.with.view">[[range.join.with.view]]</a>
2314
+
2315
+ ``` cpp
2316
+ namespace std::ranges {
2317
+ template<class R, class P>
2318
+ concept compatible-joinable-ranges = // exposition only
2319
+ common_with<range_value_t<R>, range_value_t<P>> &&
2320
+ common_reference_with<range_reference_t<R>, range_reference_t<P>> &&
2321
+ common_reference_with<range_rvalue_reference_t<R>, range_rvalue_reference_t<P>>;
2322
+
2323
+ template<class R>
2324
+ concept bidirectional-common = bidirectional_range<R> && common_range<R>; // exposition only
2325
+
2326
+ template<input_range V, forward_range Pattern>
2327
+ requires view<V> && input_range<range_reference_t<V>>
2328
+ && view<Pattern>
2329
+ && compatible-joinable-ranges<range_reference_t<V>, Pattern>
2330
+ class join_with_view : public view_interface<join_with_view<V, Pattern>> {
2331
+ using InnerRng = range_reference_t<V>; // exposition only
2332
+
2333
+ V base_ = V(); // exposition only
2334
+ non-propagating-cache<iterator_t<V>> outer_it_; // exposition only, present only
2335
+ // when !forward_range<V>
2336
+ non-propagating-cache<remove_cv_t<InnerRng>> inner_; // exposition only, present only
2337
+ // if is_reference_v<InnerRng> is false
2338
+ Pattern pattern_ = Pattern(); // exposition only
2339
+
2340
+ // [range.join.with.iterator], class template join_with_view::iterator
2341
+ template<bool Const> struct iterator; // exposition only
2342
+
2343
+ // [range.join.with.sentinel], class template join_with_view::sentinel
2344
+ template<bool Const> struct sentinel; // exposition only
2345
+
2346
+ public:
2347
+ join_with_view()
2348
+ requires default_initializable<V> && default_initializable<Pattern> = default;
2349
+
2350
+ constexpr explicit join_with_view(V base, Pattern pattern);
2351
+
2352
+ template<input_range R>
2353
+ requires constructible_from<V, views::all_t<R>> &&
2354
+ constructible_from<Pattern, single_view<range_value_t<InnerRng>>>
2355
+ constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);
2356
+
2357
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
2358
+ constexpr V base() && { return std::move(base_); }
2359
+
2360
+ constexpr auto begin() {
2361
+ if constexpr (forward_range<V>) {
2362
+ constexpr bool use_const =
2363
+ simple-view<V> && is_reference_v<InnerRng> && simple-view<Pattern>;
2364
+ return iterator<use_const>{*this, ranges::begin(base_)};
2365
+ }
2366
+ else {
2367
+ outer_it_ = ranges::begin(base_);
2368
+ return iterator<false>{*this};
2369
+ }
2370
+ }
2371
+ constexpr auto begin() const
2372
+ requires forward_range<const V> &&
2373
+ forward_range<const Pattern> &&
2374
+ is_reference_v<range_reference_t<const V>> &&
2375
+ input_range<range_reference_t<const V>> {
2376
+ return iterator<true>{*this, ranges::begin(base_)};
2377
+ }
2378
+
2379
+ constexpr auto end() {
2380
+ if constexpr (forward_range<V> &&
2381
+ is_reference_v<InnerRng> && forward_range<InnerRng> &&
2382
+ common_range<V> && common_range<InnerRng>)
2383
+ return iterator<simple-view<V> && simple-view<Pattern>>{*this, ranges::end(base_)};
2384
+ else
2385
+ return sentinel<simple-view<V> && simple-view<Pattern>>{*this};
2386
+ }
2387
+ constexpr auto end() const
2388
+ requires forward_range<const V> && forward_range<const Pattern> &&
2389
+ is_reference_v<range_reference_t<const V>> &&
2390
+ input_range<range_reference_t<const V>> {
2391
+ using InnerConstRng = range_reference_t<const V>;
2392
+ if constexpr (forward_range<InnerConstRng> &&
2393
+ common_range<const V> && common_range<InnerConstRng>)
2394
+ return iterator<true>{*this, ranges::end(base_)};
2395
+ else
2396
+ return sentinel<true>{*this};
2397
+ }
2398
+ };
2399
+
2400
+ template<class R, class P>
2401
+ join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>;
2402
+
2403
+ template<input_range R>
2404
+ join_with_view(R&&, range_value_t<range_reference_t<R>>)
2405
+ -> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>;
2406
+ }
2407
+ ```
2408
+
2409
+ ``` cpp
2410
+ constexpr explicit join_with_view(V base, Pattern pattern);
2411
+ ```
2412
+
2413
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pattern\_*
2414
+ with `std::move(pattern)`.
2415
+
2416
+ ``` cpp
2417
+ template<input_range R>
2418
+ requires constructible_from<V, views::all_t<R>> &&
2419
+ constructible_from<Pattern, single_view<range_value_t<InnerRng>>>
2420
+ constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);
2421
+ ```
2422
+
2423
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`
2424
+ and *pattern\_* with `views::single(std::move(e))`.
2425
+
2426
+ #### Class template `join_with_view::iterator` <a id="range.join.with.iterator">[[range.join.with.iterator]]</a>
2427
+
2428
+ ``` cpp
2429
+ namespace std::ranges {
2430
+ template<input_range V, forward_range Pattern>
2431
+ requires view<V> && input_range<range_reference_t<V>>
2432
+ && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
2433
+ template<bool Const>
2434
+ class join_with_view<V, Pattern>::iterator {
2435
+ using Parent = maybe-const<Const, join_with_view>; // exposition only
2436
+ using Base = maybe-const<Const, V>; // exposition only
2437
+ using InnerBase = range_reference_t<Base>; // exposition only
2438
+ using PatternBase = maybe-const<Const, Pattern>; // exposition only
2439
+
2440
+ using OuterIter = iterator_t<Base>; // exposition only
2441
+ using InnerIter = iterator_t<InnerBase>; // exposition only
2442
+ using PatternIter = iterator_t<PatternBase>; // exposition only
2443
+
2444
+ static constexpr bool ref-is-glvalue = is_reference_v<InnerBase>; // exposition only
2445
+
2446
+ Parent* parent_ = nullptr; // exposition only
2447
+ OuterIter outer_it_ = OuterIter(); // exposition only, present only
2448
+ // if Base models forward_range
2449
+ variant<PatternIter, InnerIter> inner_it_; // exposition only
2450
+
2451
+ constexpr iterator(Parent& parent, OuterIter outer)
2452
+ requires forward_range<Base>; // exposition only
2453
+ constexpr explicit iterator(Parent& parent)
2454
+ requires (!forward_range<Base>); // exposition only
2455
+ constexpr OuterIter& outer(); // exposition only
2456
+ constexpr const OuterIter& outer() const; // exposition only
2457
+ constexpr auto& update-inner(); // exposition only
2458
+ constexpr auto& get-inner(); // exposition only
2459
+ constexpr void satisfy(); // exposition only
2460
+
2461
+ public:
2462
+ using iterator_concept = see below;
2463
+ using iterator_category = see below; // not always present
2464
+ using value_type = see below;
2465
+ using difference_type = see below;
2466
+
2467
+ iterator() = default;
2468
+ constexpr iterator(iterator<!Const> i)
2469
+ requires Const && convertible_to<iterator_t<V>, OuterIter> &&
2470
+ convertible_to<iterator_t<InnerRng>, InnerIter> &&
2471
+ convertible_to<iterator_t<Pattern>, PatternIter>;
2472
+
2473
+ constexpr decltype(auto) operator*() const;
2474
+
2475
+ constexpr iterator& operator++();
2476
+ constexpr void operator++(int);
2477
+ constexpr iterator operator++(int)
2478
+ requires ref-is-glvalue && forward_iterator<OuterIter> &&
2479
+ forward_iterator<InnerIter>;
2480
+
2481
+ constexpr iterator& operator--()
2482
+ requires ref-is-glvalue && bidirectional_range<Base> &&
2483
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
2484
+ constexpr iterator operator--(int)
2485
+ requires ref-is-glvalue && bidirectional_range<Base> &&
2486
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
2487
+
2488
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2489
+ requires ref-is-glvalue && forward_range<Base> &&
2490
+ equality_comparable<InnerIter>;
2491
+
2492
+ friend constexpr decltype(auto) iter_move(const iterator& x) {
2493
+ using rvalue_reference = common_reference_t<
2494
+ iter_rvalue_reference_t<InnerIter>,
2495
+ iter_rvalue_reference_t<PatternIter>>;
2496
+ return visit<rvalue_reference>(ranges::iter_move, x.inner_it_);
2497
+ }
2498
+
2499
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
2500
+ requires indirectly_swappable<InnerIter, PatternIter> {
2501
+ visit(ranges::iter_swap, x.inner_it_, y.inner_it_);
2502
+ }
2503
+ };
2504
+ }
2505
+ ```
2506
+
2507
+ `iterator::iterator_concept` is defined as follows:
2508
+
2509
+ - If *`ref-is-glvalue`* is `true`, *`Base`* models
2510
+ `bidirectional_range`, and *`InnerBase`* and *`PatternBase`* each
2511
+ model `bidirectional-common`, then `iterator_concept` denotes
2512
+ `bidirectional_iterator_tag`.
2513
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
2514
+ *`InnerBase`* each model `forward_range`, then `iterator_concept`
2515
+ denotes `forward_iterator_tag`.
2516
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
2517
+
2518
+ The member *typedef-name* `iterator_category` is defined if and only if
2519
+ *`ref-is-glvalue`* is `true`, and *`Base`* and *`InnerBase`* each model
2520
+ `forward_range`. In that case, `iterator::iterator_category` is defined
2521
+ as follows:
2522
+
2523
+ - Let *OUTERC* denote `iterator_traits<OuterIter>::iterator_category`,
2524
+ let *INNERC* denote `iterator_traits<InnerIter>::iterator_category`,
2525
+ and let *PATTERNC* denote
2526
+ `iterator_-traits<PatternIter>::iterator_category`.
2527
+ - If
2528
+ ``` cpp
2529
+ is_reference_v<common_reference_t<iter_reference_t<InnerIter>,
2530
+ iter_reference_t<PatternIter>>>
2531
+ ```
2532
+
2533
+ is `false`, `iterator_category` denotes `input_iterator_tag`.
2534
+ - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
2535
+ `derived_from<bidirectional_iterator_category>` and *`InnerBase`* and
2536
+ *`PatternBase`* each model `common_range`, `iterator_category` denotes
2537
+ `bidirectional_iterator_tag`.
2538
+ - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
2539
+ `derived_from<forward_iterator_tag>`, `iterator_category` denotes
2540
+ `forward_iterator_tag`.
2541
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
2542
+
2543
+ `iterator::value_type` denotes the type:
2544
+
2545
+ ``` cpp
2546
+ common_type_t<iter_value_t<InnerIter>, iter_value_t<PatternIter>>
2547
+ ```
2548
+
2549
+ `iterator::difference_type` denotes the type:
2550
+
2551
+ ``` cpp
2552
+ common_type_t<
2553
+ iter_difference_t<OuterIter>,
2554
+ iter_difference_t<InnerIter>,
2555
+ iter_difference_t<PatternIter>>
2556
+ ```
2557
+
2558
+ ``` cpp
2559
+ constexpr OuterIter& outer();
2560
+ constexpr const OuterIter& outer() const;
2561
+ ```
2562
+
2563
+ *Returns:* *outer_it\_* if *Base* models `forward_range`; otherwise,
2564
+ `*`*`parent_`*`->`*`outer_it_`*.
2565
+
2566
+ ``` cpp
2567
+ constexpr auto& update-inner();
2568
+ ```
2569
+
2570
+ *Effects:* Equivalent to:
2571
+
2572
+ ``` cpp
2573
+ if constexpr (ref-is-glvalue)
2574
+ return as-lvalue(*outer());
2575
+ else
2576
+ return parent_->inner_.emplace-deref(outer());
2577
+ ```
2578
+
2579
+ ``` cpp
2580
+ constexpr auto& get-inner();
2581
+ ```
2582
+
2583
+ *Effects:* Equivalent to:
2584
+
2585
+ ``` cpp
2586
+ if constexpr (ref-is-glvalue)
2587
+ return as-lvalue(*outer());
2588
+ else
2589
+ return *parent_->inner_;
2590
+ ```
2591
+
2592
+ ``` cpp
2593
+ constexpr void satisfy();
2594
+ ```
2595
+
2596
+ *Effects:* Equivalent to:
2597
+
2598
+ ``` cpp
2599
+ while (true) {
2600
+ if (inner_it_.index() == 0) {
2601
+ if (std::get<0>(inner_it_) != ranges::end(parent_->pattern_))
2602
+ break;
2603
+ inner_it_.emplace<1>(ranges::begin(update-inner()));
2604
+ } else {
2605
+ if (std::get<1>(inner_it_) != ranges::end(get-inner()))
2606
+ break;
2607
+ if (++outer() == ranges::end(parent_->base_)) {
2608
+ if constexpr (ref-is-glvalue)
2609
+ inner_it_.emplace<0>();
2610
+ break;
2611
+ }
2612
+ inner_it_.emplace<0>(ranges::begin(parent_->pattern_));
2613
+ }
2614
+ }
2615
+ ```
2616
+
2617
+ [*Note 1*: `join_with_view` iterators use the *satisfy* function to
2618
+ skip over empty inner ranges. — *end note*]
2619
+
2620
+ ``` cpp
2621
+ constexpr iterator(Parent& parent, OuterIter outer)
2622
+ requires forward_range<Base>;
2623
+ constexpr explicit iterator(Parent& parent)
2624
+ requires (!forward_range<Base>);
2625
+ ```
2626
+
2627
+ *Effects:* Initializes *parent\_* with `addressof(parent)`. For the
2628
+ first overload, also initializes *outer_it\_* with `std::move(outer)`.
2629
+ Then, equivalent to:
2630
+
2631
+ ``` cpp
2632
+ if (outer() != ranges::end(parent_->base_)) {
2633
+ inner_it_.emplace<1>(ranges::begin(update-inner()));
2634
+ satisfy();
2635
+ }
2636
+ ```
2637
+
2638
+ ``` cpp
2639
+ constexpr iterator(iterator<!Const> i)
2640
+ requires Const && convertible_to<iterator_t<V>, OuterIter> &&
2641
+ convertible_to<iterator_t<InnerRng>, InnerIter> &&
2642
+ convertible_to<iterator_t<Pattern>, PatternIter>;
2643
+ ```
2644
+
2645
+ *Effects:* Initializes *outer_it\_* with `std::move(i.`*`outer_it_`*`)`
2646
+ and *parent\_* with `i.`*`parent_`*. Then, equivalent to:
2647
+
2648
+ ``` cpp
2649
+ if (i.inner_it_.index() == 0)
2650
+ inner_it_.emplace<0>(std::get<0>(std::move(i.inner_it_)));
2651
+ else
2652
+ inner_it_.emplace<1>(std::get<1>(std::move(i.inner_it_)));
2653
+ ```
2654
+
2655
+ [*Note 2*: `Const` can only be `true` when *Base* models
2656
+ `forward_range`. — *end note*]
2657
+
2658
+ ``` cpp
2659
+ constexpr decltype(auto) operator*() const;
2660
+ ```
2661
+
2662
+ *Effects:* Equivalent to:
2663
+
2664
+ ``` cpp
2665
+ using reference =
2666
+ common_reference_t<iter_reference_t<InnerIter>, iter_reference_t<PatternIter>>;
2667
+ return visit([](auto& it) -> reference { return *it; }, inner_it_);
2668
+ ```
2669
+
2670
+ ``` cpp
2671
+ constexpr iterator& operator++();
2672
+ ```
2673
+
2674
+ *Effects:* Equivalent to:
2675
+
2676
+ ``` cpp
2677
+ visit([](auto& it){ ++it; }, inner_it_);
2678
+ satisfy();
2679
+ return *this;
2680
+ ```
2681
+
2682
+ ``` cpp
2683
+ constexpr void operator++(int);
2684
+ ```
2685
+
2686
+ *Effects:* Equivalent to `++*this`.
2687
+
2688
+ ``` cpp
2689
+ constexpr iterator operator++(int)
2690
+ requires ref-is-glvalue && forward_iterator<OuterIter> && forward_iterator<InnerIter>;
2691
+ ```
2692
+
2693
+ *Effects:* Equivalent to:
2694
+
2695
+ ``` cpp
2696
+ iterator tmp = *this;
2697
+ ++*this;
2698
+ return tmp;
2699
+ ```
2700
+
2701
+ ``` cpp
2702
+ constexpr iterator& operator--()
2703
+ requires ref-is-glvalue && bidirectional_range<Base> &&
2704
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
2705
+ ```
2706
+
2707
+ *Effects:* Equivalent to:
2708
+
2709
+ ``` cpp
2710
+ if (outer_it_ == ranges::end(parent_->base_)) {
2711
+ auto&& inner = *--outer_it_;
2712
+ inner_it_.emplace<1>(ranges::end(inner));
2713
+ }
2714
+
2715
+ while (true) {
2716
+ if (inner_it_.index() == 0) {
2717
+ auto& it = std::get<0>(inner_it_);
2718
+ if (it == ranges::begin(parent_->pattern_)) {
2719
+ auto&& inner = *--outer_it_;
2720
+ inner_it_.emplace<1>(ranges::end(inner));
2721
+ } else {
2722
+ break;
2723
+ }
2724
+ } else {
2725
+ auto& it = std::get<1>(inner_it_);
2726
+ auto&& inner = *outer_it_;
2727
+ if (it == ranges::begin(inner)) {
2728
+ inner_it_.emplace<0>(ranges::end(parent_->pattern_));
2729
+ } else {
2730
+ break;
2731
+ }
2732
+ }
2733
+ }
2734
+ visit([](auto& it){ --it; }, inner_it_);
2735
+ return *this;
2736
+ ```
2737
+
2738
+ ``` cpp
2739
+ constexpr iterator operator--(int)
2740
+ requires ref-is-glvalue && bidirectional_range<Base> &&
2741
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
2742
+ ```
2743
+
2744
+ *Effects:* Equivalent to:
2745
+
2746
+ ``` cpp
2747
+ iterator tmp = *this;
2748
+ --*this;
2749
+ return tmp;
2750
+ ```
2751
+
2752
+ ``` cpp
2753
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
2754
+ requires ref-is-glvalue && forward_range<Base> &&
2755
+ equality_comparable<InnerIter>;
2756
+ ```
2757
+
2758
+ *Effects:* Equivalent to:
2759
+
2760
+ ``` cpp
2761
+ return x.outer_it_ == y.outer_it_ && x.inner_it_ == y.inner_it_;
2762
+ ```
2763
+
2764
+ #### Class template `join_with_view::sentinel` <a id="range.join.with.sentinel">[[range.join.with.sentinel]]</a>
2765
+
2766
+ ``` cpp
2767
+ namespace std::ranges {
2768
+ template<input_range V, forward_range Pattern>
2769
+ requires view<V> && input_range<range_reference_t<V>>
2770
+ && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
2771
+ template<bool Const>
2772
+ class join_with_view<V, Pattern>::sentinel {
2773
+ using Parent = maybe-const<Const, join_with_view>; // exposition only
2774
+ using Base = maybe-const<Const, V>; // exposition only
2775
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
2776
+
2777
+ constexpr explicit sentinel(Parent& parent); // exposition only
2778
+
2779
+ public:
2780
+ sentinel() = default;
2781
+ constexpr sentinel(sentinel<!Const> s)
2782
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
2783
+
2784
+ template<bool OtherConst>
2785
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
2786
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
2787
  };
2788
  }
2789
  ```
2790
 
2791
  ``` cpp
 
2800
  ```
2801
 
2802
  *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
2803
 
2804
  ``` cpp
2805
+ template<bool OtherConst>
2806
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
2807
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
2808
  ```
2809
 
2810
+ *Effects:* Equivalent to: `return x.`*`outer`*`() == y.`*`end_`*`;`
2811
 
2812
+ ### Lazy split view <a id="range.lazy.split">[[range.lazy.split]]</a>
2813
 
2814
+ #### Overview <a id="range.lazy.split.overview">[[range.lazy.split.overview]]</a>
2815
 
2816
+ `lazy_split_view` takes a view and a delimiter, and splits the view into
2817
  subranges on the delimiter. The delimiter can be a single element or a
2818
+ view of elements.
2819
 
2820
+ The name `views::lazy_split` denotes a range adaptor object
2821
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
2822
+ expression `views::lazy_split(E, F)` is expression-equivalent to
2823
+ `lazy_split_view(E, F)`.
2824
 
2825
  [*Example 1*:
2826
 
2827
  ``` cpp
2828
  string str{"the quick brown fox"};
2829
+ for (auto word : str | views::lazy_split(' ')) {
 
2830
  for (char ch : word)
2831
  cout << ch;
2832
  cout << '*';
2833
  }
2834
+ // The above prints the*quick*brown*fox*
2835
  ```
2836
 
2837
  — *end example*]
2838
 
2839
+ #### Class template `lazy_split_view` <a id="range.lazy.split.view">[[range.lazy.split.view]]</a>
2840
 
2841
  ``` cpp
2842
  namespace std::ranges {
2843
  template<auto> struct require-constant; // exposition only
2844
 
 
2850
 
2851
  template<input_range V, forward_range Pattern>
2852
  requires view<V> && view<Pattern> &&
2853
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2854
  (forward_range<V> || tiny-range<Pattern>)
2855
+ class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {
2856
  private:
2857
  V base_ = V(); // exposition only
2858
  Pattern pattern_ = Pattern(); // exposition only
2859
+
2860
+ non-propagating-cache<iterator_t<V>> current_; // exposition only, present only
2861
+ // if forward_range<V> is false
2862
+
2863
+ // [range.lazy.split.outer], class template lazy_split_view::outer-iterator
2864
  template<bool> struct outer-iterator; // exposition only
2865
+
2866
+ // [range.lazy.split.inner], class template lazy_split_view::inner-iterator
2867
  template<bool> struct inner-iterator; // exposition only
2868
+
2869
  public:
2870
+ lazy_split_view()
2871
+ requires default_initializable<V> && default_initializable<Pattern> = default;
2872
+ constexpr explicit lazy_split_view(V base, Pattern pattern);
2873
 
2874
  template<input_range R>
2875
  requires constructible_from<V, views::all_t<R>> &&
2876
  constructible_from<Pattern, single_view<range_value_t<R>>>
2877
+ constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);
2878
 
2879
  constexpr V base() const & requires copy_constructible<V> { return base_; }
2880
  constexpr V base() && { return std::move(base_); }
2881
 
2882
  constexpr auto begin() {
2883
+ if constexpr (forward_range<V>) {
2884
+ return outer-iterator<simple-view<V> && simple-view<Pattern>>
2885
+ {*this, ranges::begin(base_)};
2886
+ } else {
2887
  current_ = ranges::begin(base_);
2888
  return outer-iterator<false>{*this};
2889
  }
2890
  }
2891
 
2892
  constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
2893
  return outer-iterator<true>{*this, ranges::begin(base_)};
2894
  }
2895
 
2896
  constexpr auto end() requires forward_range<V> && common_range<V> {
2897
+ return outer-iterator<simple-view<V> && simple-view<Pattern>>
2898
+ {*this, ranges::end(base_)};
2899
  }
2900
 
2901
  constexpr auto end() const {
2902
  if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
2903
  return outer-iterator<true>{*this, ranges::end(base_)};
 
2905
  return default_sentinel;
2906
  }
2907
  };
2908
 
2909
  template<class R, class P>
2910
+ lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>;
2911
 
2912
  template<input_range R>
2913
+ lazy_split_view(R&&, range_value_t<R>)
2914
+ -> lazy_split_view<views::all_t<R>, single_view<range_value_t<R>>>;
2915
  }
2916
  ```
2917
 
2918
  ``` cpp
2919
+ constexpr explicit lazy_split_view(V base, Pattern pattern);
2920
  ```
2921
 
2922
  *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
2923
  with `std::move(pattern)`.
2924
 
2925
  ``` cpp
2926
  template<input_range R>
2927
  requires constructible_from<V, views::all_t<R>> &&
2928
  constructible_from<Pattern, single_view<range_value_t<R>>>
2929
+ constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);
2930
  ```
2931
 
2932
  *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
2933
+ and *pattern\_* with `views::single(std::move(e))`.
2934
 
2935
+ #### Class template `lazy_split_view::outer-iterator` <a id="range.lazy.split.outer">[[range.lazy.split.outer]]</a>
2936
 
2937
  ``` cpp
2938
  namespace std::ranges {
2939
  template<input_range V, forward_range Pattern>
2940
  requires view<V> && view<Pattern> &&
2941
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
2942
  (forward_range<V> || tiny-range<Pattern>)
2943
  template<bool Const>
2944
+ struct lazy_split_view<V, Pattern>::outer-iterator {
2945
  private:
2946
+ using Parent = maybe-const<Const, lazy_split_view>; // exposition only
2947
+ using Base = maybe-const<Const, V>; // exposition only
 
 
2948
  Parent* parent_ = nullptr; // exposition only
2949
+
2950
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only, present only
2951
+ // if V models forward_range
2952
+
2953
+ bool trailing_empty_ = false; // exposition only
2954
 
2955
  public:
2956
  using iterator_concept =
2957
  conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
2958
+
2959
+ using iterator_category = input_iterator_tag; // present only if Base
2960
+ // models forward_range
2961
+
2962
+ // [range.lazy.split.outer.value], class lazy_split_view::outer-iterator::value_type
2963
  struct value_type;
2964
  using difference_type = range_difference_t<Base>;
2965
 
2966
  outer-iterator() = default;
2967
  constexpr explicit outer-iterator(Parent& parent)
 
2989
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
2990
  };
2991
  }
2992
  ```
2993
 
2994
+ Many of the specifications in [[range.lazy.split]] refer to the notional
2995
+ member *current* of *`outer-iterator`*. *current* is equivalent to
2996
+ *`current_`* if `V` models `forward_range`, and `*parent_->current_`
2997
+ otherwise.
2998
 
2999
  ``` cpp
3000
  constexpr explicit outer-iterator(Parent& parent)
3001
  requires (!forward_range<Base>);
3002
  ```
 
3031
 
3032
  *Effects:* Equivalent to:
3033
 
3034
  ``` cpp
3035
  const auto end = ranges::end(parent_->base_);
3036
+ if (current == end) {
3037
+ trailing_empty_ = false;
3038
+ return *this;
3039
+ }
3040
  const auto [pbegin, pend] = subrange{parent_->pattern_};
3041
  if (pbegin == pend) ++current;
3042
+ else if constexpr (tiny-range<Pattern>) {
3043
+ current = ranges::find(std::move(current), end, *pbegin);
3044
+ if (current != end) {
3045
+ ++current;
3046
+ if (current == end)
3047
+ trailing_empty_ = true;
3048
+ }
3049
+ }
3050
  else {
3051
  do {
3052
+ auto [b, p] = ranges::mismatch(current, end, pbegin, pend);
 
3053
  if (p == pend) {
3054
+ current = b;
3055
+ if (current == end)
3056
+ trailing_empty_ = true;
3057
  break; // The pattern matched; skip it
3058
  }
3059
  } while (++current != end);
3060
  }
3061
  return *this;
 
3064
  ``` cpp
3065
  friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
3066
  requires forward_range<Base>;
3067
  ```
3068
 
3069
+ *Effects:* Equivalent to:
3070
+
3071
+ ``` cpp
3072
+ return x.current_ == y.current_ && x.trailing_empty_ == y.trailing_empty_;
3073
+ ```
3074
 
3075
  ``` cpp
3076
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
3077
  ```
3078
 
3079
  *Effects:* Equivalent to:
 
3080
 
3081
+ ``` cpp
3082
+ return x.current == ranges::end(x.parent_->base_) && !x.trailing_empty_;
3083
+ ```
3084
+
3085
+ #### Class `lazy_split_view::outer-iterator::value_type` <a id="range.lazy.split.outer.value">[[range.lazy.split.outer.value]]</a>
3086
 
3087
  ``` cpp
3088
  namespace std::ranges {
3089
  template<input_range V, forward_range Pattern>
3090
  requires view<V> && view<Pattern> &&
3091
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
3092
  (forward_range<V> || tiny-range<Pattern>)
3093
  template<bool Const>
3094
+ struct lazy_split_view<V, Pattern>::outer-iterator<Const>::value_type
3095
  : view_interface<value_type> {
3096
  private:
3097
  outer-iterator i_ = outer-iterator(); // exposition only
3098
+
3099
  public:
3100
  value_type() = default;
3101
  constexpr explicit value_type(outer-iterator i);
3102
 
3103
+ constexpr inner-iterator<Const> begin() const;
3104
+ constexpr default_sentinel_t end() const noexcept;
 
3105
  };
3106
  }
3107
  ```
3108
 
3109
  ``` cpp
 
3111
  ```
3112
 
3113
  *Effects:* Initializes *i\_* with `std::move(i)`.
3114
 
3115
  ``` cpp
3116
+ constexpr inner-iterator<Const> begin() const;
3117
  ```
3118
 
3119
  *Effects:* Equivalent to:
3120
  `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
3121
 
3122
  ``` cpp
3123
+ constexpr default_sentinel_t end() const noexcept;
 
 
 
 
 
 
 
3124
  ```
3125
 
3126
  *Effects:* Equivalent to: `return default_sentinel;`
3127
 
3128
+ #### Class template `lazy_split_view::inner-iterator` <a id="range.lazy.split.inner">[[range.lazy.split.inner]]</a>
3129
 
3130
  ``` cpp
3131
  namespace std::ranges {
3132
  template<input_range V, forward_range Pattern>
3133
  requires view<V> && view<Pattern> &&
3134
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
3135
  (forward_range<V> || tiny-range<Pattern>)
3136
  template<bool Const>
3137
+ struct lazy_split_view<V, Pattern>::inner-iterator {
3138
  private:
3139
+ using Base = maybe-const<Const, V>; // exposition only
3140
  outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
3141
  bool incremented_ = false; // exposition only
3142
+
3143
  public:
3144
  using iterator_concept = typename outer-iterator<Const>::iterator_concept;
3145
+
3146
+ using iterator_category = see belownc; // present only if Base
3147
+ // models forward_range
3148
  using value_type = range_value_t<Base>;
3149
  using difference_type = range_difference_t<Base>;
3150
 
3151
  inner-iterator() = default;
3152
  constexpr explicit inner-iterator(outer-iterator<Const> i);
3153
 
3154
+ constexpr const iterator_t<Base>& base() const & noexcept;
3155
+ constexpr iterator_t<Base> base() && requires forward_range<V>;
3156
+
3157
  constexpr decltype(auto) operator*() const { return *i_.current; }
3158
 
3159
  constexpr inner-iterator& operator++();
3160
  constexpr decltype(auto) operator++(int) {
3161
+ if constexpr (forward_range<Base>) {
3162
  auto tmp = *this;
3163
  ++*this;
3164
  return tmp;
3165
  } else
3166
  ++*this;
 
3181
  requires indirectly_swappable<iterator_t<Base>>;
3182
  };
3183
  }
3184
  ```
3185
 
3186
+ If *`Base`* does not model `forward_range` there is no member
3187
+ `iterator_category`. Otherwise, the *typedef-name* `iterator_category`
3188
+ denotes:
3189
 
3190
  - `forward_iterator_tag` if
3191
  `iterator_traits<iterator_t<Base>>::iterator_category` models
3192
  `derived_from<forward_iterator_tag>`;
3193
  - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
 
3196
  constexpr explicit inner-iterator(outer-iterator<Const> i);
3197
  ```
3198
 
3199
  *Effects:* Initializes *i\_* with `std::move(i)`.
3200
 
3201
+ ``` cpp
3202
+ constexpr const iterator_t<Base>& base() const & noexcept;
3203
+ ```
3204
+
3205
+ *Effects:* Equivalent to: `return `*`i_`*`.`*`current`*`;`
3206
+
3207
+ ``` cpp
3208
+ constexpr iterator_t<Base> base() && requires forward_range<V>;
3209
+ ```
3210
+
3211
+ *Effects:* Equivalent to: `return std::move(`*`i_`*`.`*`current`*`);`
3212
+
3213
  ``` cpp
3214
  constexpr inner-iterator& operator++();
3215
  ```
3216
 
3217
  *Effects:* Equivalent to:
 
3268
  ```
3269
 
3270
  *Effects:* Equivalent to
3271
  `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
3272
 
3273
+ ### Split view <a id="range.split">[[range.split]]</a>
3274
+
3275
+ #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
3276
+
3277
+ `split_view` takes a view and a delimiter, and splits the view into
3278
+ `subrange`s on the delimiter. The delimiter can be a single element or a
3279
+ view of elements.
3280
+
3281
+ The name `views::split` denotes a range adaptor object
3282
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
3283
+ expression `views::split(E, F)` is expression-equivalent to
3284
+ `split_view(E, F)`.
3285
+
3286
+ [*Example 1*:
3287
+
3288
+ ``` cpp
3289
+ string str{"the quick brown fox"};
3290
+ for (auto word : views::split(str, ' ')) {
3291
+ cout << string_view(word) << '*';
3292
+ }
3293
+ // The above prints the*quick*brown*fox*
3294
+ ```
3295
+
3296
+ — *end example*]
3297
+
3298
+ #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
3299
+
3300
+ ``` cpp
3301
+ namespace std::ranges {
3302
+ template<forward_range V, forward_range Pattern>
3303
+ requires view<V> && view<Pattern> &&
3304
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
3305
+ class split_view : public view_interface<split_view<V, Pattern>> {
3306
+ private:
3307
+ V base_ = V(); // exposition only
3308
+ Pattern pattern_ = Pattern(); // exposition only
3309
+
3310
+ // [range.split.iterator], class split_view::iterator
3311
+ struct iterator; // exposition only
3312
+
3313
+ // [range.split.sentinel], class split_view::sentinel
3314
+ struct sentinel; // exposition only
3315
+
3316
+ public:
3317
+ split_view()
3318
+ requires default_initializable<V> && default_initializable<Pattern> = default;
3319
+ constexpr explicit split_view(V base, Pattern pattern);
3320
+
3321
+ template<forward_range R>
3322
+ requires constructible_from<V, views::all_t<R>> &&
3323
+ constructible_from<Pattern, single_view<range_value_t<R>>>
3324
+ constexpr explicit split_view(R&& r, range_value_t<R> e);
3325
+
3326
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
3327
+ constexpr V base() && { return std::move(base_); }
3328
+
3329
+ constexpr iterator begin();
3330
+
3331
+ constexpr auto end() {
3332
+ if constexpr (common_range<V>) {
3333
+ return iterator{*this, ranges::end(base_), {}};
3334
+ } else {
3335
+ return sentinel{*this};
3336
+ }
3337
+ }
3338
+
3339
+ constexpr subrange<iterator_t<V>> find-next(iterator_t<V>); // exposition only
3340
+ };
3341
+
3342
+ template<class R, class P>
3343
+ split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
3344
+
3345
+ template<forward_range R>
3346
+ split_view(R&&, range_value_t<R>)
3347
+ -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
3348
+ }
3349
+ ```
3350
+
3351
+ ``` cpp
3352
+ constexpr explicit split_view(V base, Pattern pattern);
3353
+ ```
3354
+
3355
+ *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
3356
+ with `std::move(pattern)`.
3357
+
3358
+ ``` cpp
3359
+ template<forward_range R>
3360
+ requires constructible_from<V, views::all_t<R>> &&
3361
+ constructible_from<Pattern, single_view<range_value_t<R>>>
3362
+ constexpr explicit split_view(R&& r, range_value_t<R> e);
3363
+ ```
3364
+
3365
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
3366
+ and *pattern\_* with `views::single(std::move(e))`.
3367
+
3368
+ ``` cpp
3369
+ constexpr iterator begin();
3370
+ ```
3371
+
3372
+ *Returns:*
3373
+ `{*this, ranges::begin(`*`base_`*`), `*`find-next`*`(ranges::begin(`*`base_`*`))}`.
3374
+
3375
+ *Remarks:* In order to provide the amortized constant time complexity
3376
+ required by the `range` concept, this function caches the result within
3377
+ the `split_view` for use on subsequent calls.
3378
+
3379
+ ``` cpp
3380
+ constexpr subrange<iterator_t<V>> find-next(iterator_t<V> it);
3381
+ ```
3382
+
3383
+ *Effects:* Equivalent to:
3384
+
3385
+ ``` cpp
3386
+ auto [b, e] = ranges::search(subrange(it, ranges::end(base_)), pattern_);
3387
+ if (b != ranges::end(base_) && ranges::empty(pattern_)) {
3388
+ ++b;
3389
+ ++e;
3390
+ }
3391
+ return {b, e};
3392
+ ```
3393
+
3394
+ #### Class `split_view::iterator` <a id="range.split.iterator">[[range.split.iterator]]</a>
3395
+
3396
+ ``` cpp
3397
+ namespace std::ranges {
3398
+ template<forward_range V, forward_range Pattern>
3399
+ requires view<V> && view<Pattern> &&
3400
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
3401
+ class split_view<V, Pattern>::iterator {
3402
+ private:
3403
+ split_view* parent_ = nullptr; // exposition only
3404
+ iterator_t<V> cur_ = iterator_t<V>(); // exposition only
3405
+ subrange<iterator_t<V>> next_ = subrange<iterator_t<V>>(); // exposition only
3406
+ bool trailing_empty_ = false; // exposition only
3407
+
3408
+ public:
3409
+ using iterator_concept = forward_iterator_tag;
3410
+ using iterator_category = input_iterator_tag;
3411
+ using value_type = subrange<iterator_t<V>>;
3412
+ using difference_type = range_difference_t<V>;
3413
+
3414
+ iterator() = default;
3415
+ constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
3416
+
3417
+ constexpr iterator_t<V> base() const;
3418
+ constexpr value_type operator*() const;
3419
+
3420
+ constexpr iterator& operator++();
3421
+ constexpr iterator operator++(int);
3422
+
3423
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
3424
+ };
3425
+ }
3426
+ ```
3427
+
3428
+ ``` cpp
3429
+ constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
3430
+ ```
3431
+
3432
+ *Effects:* Initializes *parent\_* with `addressof(parent)`, *cur\_* with
3433
+ `std::move(current)`, and *next\_* with `std::move(next)`.
3434
+
3435
+ ``` cpp
3436
+ constexpr iterator_t<V> base() const;
3437
+ ```
3438
+
3439
+ *Effects:* Equivalent to `return `*`cur_`*`;`
3440
+
3441
+ ``` cpp
3442
+ constexpr value_type operator*() const;
3443
+ ```
3444
+
3445
+ *Effects:* Equivalent to `return {`*`cur_`*`, `*`next_`*`.begin()};`
3446
+
3447
+ ``` cpp
3448
+ constexpr iterator& operator++();
3449
+ ```
3450
+
3451
+ *Effects:* Equivalent to:
3452
+
3453
+ ``` cpp
3454
+ cur_ = next_.begin();
3455
+ if (cur_ != ranges::end(parent_->base_)) {
3456
+ cur_ = next_.end();
3457
+ if (cur_ == ranges::end(parent_->base_)) {
3458
+ trailing_empty_ = true;
3459
+ next_ = {cur_, cur_};
3460
+ } else {
3461
+ next_ = parent_->find-next(cur_);
3462
+ }
3463
+ } else {
3464
+ trailing_empty_ = false;
3465
+ }
3466
+ return *this;
3467
+ ```
3468
+
3469
+ ``` cpp
3470
+ constexpr iterator operator++(int);
3471
+ ```
3472
+
3473
+ *Effects:* Equivalent to:
3474
+
3475
+ ``` cpp
3476
+ auto tmp = *this;
3477
+ ++*this;
3478
+ return tmp;
3479
+ ```
3480
+
3481
+ ``` cpp
3482
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
3483
+ ```
3484
+
3485
+ *Effects:* Equivalent to:
3486
+
3487
+ ``` cpp
3488
+ return x.cur_ == y.cur_ && x.trailing_empty_ == y.trailing_empty_;
3489
+ ```
3490
+
3491
+ #### Class `split_view::sentinel` <a id="range.split.sentinel">[[range.split.sentinel]]</a>
3492
+
3493
+ ``` cpp
3494
+ namespace std::ranges {
3495
+ template<forward_range V, forward_range Pattern>
3496
+ requires view<V> && view<Pattern> &&
3497
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
3498
+ struct split_view<V, Pattern>::sentinel {
3499
+ private:
3500
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
3501
+
3502
+ public:
3503
+ sentinel() = default;
3504
+ constexpr explicit sentinel(split_view& parent);
3505
+
3506
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
3507
+ };
3508
+ }
3509
+ ```
3510
+
3511
+ ``` cpp
3512
+ constexpr explicit sentinel(split_view& parent);
3513
+ ```
3514
+
3515
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
3516
+
3517
+ ``` cpp
3518
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
3519
+ ```
3520
+
3521
+ *Effects:* Equivalent to:
3522
+ `return x.`*`cur_`*` == y.`*`end_`*` && !x.`*`trailing_empty_`*`;`
3523
+
3524
  ### Counted view <a id="range.counted">[[range.counted]]</a>
3525
 
3526
+ A counted view presents a view of the elements of the counted range
3527
  [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
3528
  non-negative integer `n`.
3529
 
3530
  The name `views::counted` denotes a customization point object
3531
  [[customization.point.object]]. Let `E` and `F` be expressions, let `T`
 
3538
  instantiation. — *end note*]
3539
 
3540
  Otherwise, `views::counted(E, F)` is expression-equivalent to:
3541
 
3542
  - If `T` models `contiguous_iterator`, then
3543
+ `span(to_address(E), static_cast<size_t>(static_-{}cast<D>(F)))`.
3544
  - Otherwise, if `T` models `random_access_iterator`, then
3545
+ `subrange(E, E + static_cast<D>(F))`, except that `E` is evaluated
3546
  only once.
3547
+ - Otherwise, `subrange(counted_iterator(E, F), default_sentinel)`.
3548
 
3549
  ### Common view <a id="range.common">[[range.common]]</a>
3550
 
3551
  #### Overview <a id="range.common.overview">[[range.common.overview]]</a>
3552
 
3553
+ `common_view` takes a view which has different types for its iterator
3554
+ and sentinel and turns it into a view of the same elements with an
3555
  iterator and sentinel of the same type.
3556
 
3557
  [*Note 1*: `common_view` is useful for calling legacy algorithms that
3558
  expect a range’s iterator and sentinel types to be the
3559
  same. — *end note*]
 
3573
  template<class ForwardIterator>
3574
  size_t count(ForwardIterator first, ForwardIterator last);
3575
 
3576
  template<forward_range R>
3577
  void my_algo(R&& r) {
3578
+ auto&& common = views::common(r);
3579
  auto cnt = count(common.begin(), common.end());
3580
  // ...
3581
  }
3582
  ```
3583
 
 
3590
  template<view V>
3591
  requires (!common_range<V> && copyable<iterator_t<V>>)
3592
  class common_view : public view_interface<common_view<V>> {
3593
  private:
3594
  V base_ = V(); // exposition only
3595
+
3596
  public:
3597
+ common_view() requires default_initializable<V> = default;
3598
 
3599
  constexpr explicit common_view(V r);
3600
 
 
 
 
 
3601
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3602
  constexpr V base() && { return std::move(base_); }
3603
 
3604
  constexpr auto begin() {
3605
  if constexpr (random_access_range<V> && sized_range<V>)
 
3615
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
3616
  }
3617
 
3618
  constexpr auto end() {
3619
  if constexpr (random_access_range<V> && sized_range<V>)
3620
+ return ranges::begin(base_) + ranges::distance(base_);
3621
  else
3622
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
3623
  }
3624
 
3625
  constexpr auto end() const requires range<const V> {
3626
  if constexpr (random_access_range<const V> && sized_range<const V>)
3627
+ return ranges::begin(base_) + ranges::distance(base_);
3628
  else
3629
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
3630
  }
3631
 
3632
  constexpr auto size() requires sized_range<V> {
 
3646
  constexpr explicit common_view(V base);
3647
  ```
3648
 
3649
  *Effects:* Initializes *base\_* with `std::move(base)`.
3650
 
 
 
 
 
 
 
 
 
3651
  ### Reverse view <a id="range.reverse">[[range.reverse]]</a>
3652
 
3653
  #### Overview <a id="range.reverse.overview">[[range.reverse.overview]]</a>
3654
 
3655
+ `reverse_view` takes a bidirectional view and produces another view that
3656
+ iterates the same elements in reverse order.
3657
 
3658
  The name `views::reverse` denotes a range adaptor object
3659
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
3660
  `views::reverse(E)` is expression-equivalent to:
3661
 
3662
  - If the type of `E` is a (possibly cv-qualified) specialization of
3663
  `reverse_view`, equivalent to `E.base()`.
3664
+ - Otherwise, if the type of `E` is cv
3665
+ `subrange<reverse_iterator<I>, reverse_iterator<I>, K>` for some
3666
+ iterator type `I` and value `K` of type `subrange_kind`,
 
 
 
3667
  - if `K` is `subrange_kind::sized`, equivalent to:
3668
  ``` cpp
3669
  subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
3670
  ```
3671
  - otherwise, equivalent to:
 
3678
 
3679
  [*Example 1*:
3680
 
3681
  ``` cpp
3682
  vector<int> is {0,1,2,3,4};
3683
+ for (int i : is | views::reverse)
3684
+ cout << i << ' '; // prints 4 3 2 1 0
 
3685
  ```
3686
 
3687
  — *end example*]
3688
 
3689
  #### Class template `reverse_view` <a id="range.reverse.view">[[range.reverse.view]]</a>
 
3693
  template<view V>
3694
  requires bidirectional_range<V>
3695
  class reverse_view : public view_interface<reverse_view<V>> {
3696
  private:
3697
  V base_ = V(); // exposition only
3698
+
3699
  public:
3700
+ reverse_view() requires default_initializable<V> = default;
3701
 
3702
  constexpr explicit reverse_view(V r);
3703
 
3704
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3705
  constexpr V base() && { return std::move(base_); }
 
3712
  constexpr auto end() const requires common_range<const V>;
3713
 
3714
  constexpr auto size() requires sized_range<V> {
3715
  return ranges::size(base_);
3716
  }
3717
+
3718
  constexpr auto size() const requires sized_range<const V> {
3719
  return ranges::size(base_);
3720
  }
3721
  };
3722
 
 
3749
  constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
3750
  constexpr auto begin() const requires common_range<const V>;
3751
  ```
3752
 
3753
  *Effects:* Equivalent to:
3754
+ `return make_reverse_iterator(ranges::end(`*`base_`*`));`
3755
 
3756
  ``` cpp
3757
  constexpr reverse_iterator<iterator_t<V>> end();
3758
  constexpr auto end() const requires common_range<const V>;
3759
  ```
3760
 
3761
  *Effects:* Equivalent to:
3762
+ `return make_reverse_iterator(ranges::begin(`*`base_`*`));`
3763
+
3764
+ ### As const view <a id="range.as.const">[[range.as.const]]</a>
3765
+
3766
+ #### Overview <a id="range.as.const.overview">[[range.as.const.overview]]</a>
3767
+
3768
+ `as_const_view` presents a view of an underlying sequence as constant.
3769
+ That is, the elements of an `as_const_view` cannot be modified.
3770
+
3771
+ The name `views::as_const` denotes a range adaptor object
3772
+ [[range.adaptor.object]]. Let `E` be an expression, let `T` be
3773
+ `decltype((E))`, and let `U` be `remove_cvref_t<T>`. The expression
3774
+ `views::as_const(E)` is expression-equivalent to:
3775
+
3776
+ - If `views::all_t<T>` models `constant_range`, then `views::all(E)`.
3777
+ - Otherwise, if `U` denotes `empty_view<X>` for some type `X`, then
3778
+ `auto(views::empty<const X>)`.
3779
+ - Otherwise, if `U` denotes `span<X, Extent>` for some type `X` and some
3780
+ extent `Extent`, then `span<const X, Extent>(E)`.
3781
+ - Otherwise, if `U` denotes `ref_view<X>` for some type `X` and
3782
+ `const X` models `constant_range`, then
3783
+ `ref_view(static_cast<const X&>(E.base()))`.
3784
+ - Otherwise, if `E` is an lvalue, `const U` models `constant_range`, and
3785
+ `U` does not model `view`, then `ref_view(static_cast<const U&>(E))`.
3786
+ - Otherwise, `as_const_view(E)`.
3787
+
3788
+ [*Example 1*:
3789
+
3790
+ ``` cpp
3791
+ template<constant_range R>
3792
+ void cant_touch_this(R&&);
3793
+
3794
+ vector<char> hammer = {'m', 'c'};
3795
+ span<char> beat = hammer;
3796
+ cant_touch_this(views::as_const(beat)); // will not modify the elements of hammer
3797
+ ```
3798
+
3799
+ — *end example*]
3800
+
3801
+ #### Class template `as_const_view` <a id="range.as.const.view">[[range.as.const.view]]</a>
3802
+
3803
+ ``` cpp
3804
+ namespace std::ranges {
3805
+ template<view V>
3806
+ requires input_range<V>
3807
+ class as_const_view : public view_interface<as_const_view<V>> {
3808
+ V base_ = V(); // exposition only
3809
+
3810
+ public:
3811
+ as_const_view() requires default_initializable<V> = default;
3812
+ constexpr explicit as_const_view(V base);
3813
+
3814
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
3815
+ constexpr V base() && { return std::move(base_); }
3816
+
3817
+ constexpr auto begin() requires (!simple-view<V>) { return ranges::cbegin(base_); }
3818
+ constexpr auto begin() const requires range<const V> { return ranges::cbegin(base_); }
3819
+
3820
+ constexpr auto end() requires (!simple-view<V>) { return ranges::cend(base_); }
3821
+ constexpr auto end() const requires range<const V> { return ranges::cend(base_); }
3822
+
3823
+ constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
3824
+ constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
3825
+ };
3826
+
3827
+ template<class R>
3828
+ as_const_view(R&&) -> as_const_view<views::all_t<R>>;
3829
+ }
3830
+ ```
3831
+
3832
+ ``` cpp
3833
+ constexpr explicit as_const_view(V base);
3834
+ ```
3835
+
3836
+ *Effects:* Initializes *base\_* with `std::move(base)`.
3837
 
3838
  ### Elements view <a id="range.elements">[[range.elements]]</a>
3839
 
3840
  #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
3841
 
3842
+ `elements_view` takes a view of tuple-like values and a `size_t`, and
3843
+ produces a view with a value-type of the Nᵗʰ element of the adapted
3844
+ view’s value-type.
3845
 
3846
  The name `views::elements<N>` denotes a range adaptor object
3847
  [[range.adaptor.object]]. Given a subexpression `E` and constant
3848
  expression `N`, the expression `views::elements<N>(E)` is
3849
  expression-equivalent to
 
3851
 
3852
  [*Example 1*:
3853
 
3854
  ``` cpp
3855
  auto historical_figures = map{
3856
+ pair{"Lovelace"sv, 1815},
3857
  {"Turing"sv, 1912},
3858
  {"Babbage"sv, 1791},
3859
  {"Hamilton"sv, 1936}
3860
  };
3861
 
 
3870
  }
3871
  ```
3872
 
3873
  — *end example*]
3874
 
3875
+ `keys_view` is an alias for `elements_view<R, 0>`, and is useful for
3876
+ extracting keys from associative containers.
3877
 
3878
  [*Example 2*:
3879
 
3880
  ``` cpp
3881
+ auto names = historical_figures | views::keys;
3882
  for (auto&& name : names) {
3883
  cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
3884
  }
3885
  ```
3886
 
3887
  — *end example*]
3888
 
3889
+ `values_view` is an alias for `elements_view<R, 1>`, and is useful for
3890
+ extracting values from associative containers.
3891
 
3892
  [*Example 3*:
3893
 
3894
  ``` cpp
3895
  auto is_even = [](const auto x) { return x % 2 == 0; };
3896
+ cout << ranges::count_if(historical_figures | views::values, is_even); // prints 2
3897
  ```
3898
 
3899
  — *end example*]
3900
 
3901
  #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
3902
 
3903
  ``` cpp
3904
  namespace std::ranges {
3905
  template<class T, size_t N>
3906
  concept has-tuple-element = // exposition only
3907
+ tuple-like<T> && N < tuple_size_v<T>;
 
 
 
 
 
3908
 
3909
+ template<class T, size_t N>
3910
+ concept returnable-element = // exposition only
3911
+ is_reference_v<T> || move_constructible<tuple_element_t<N, T>>;
3912
 
3913
  template<input_range V, size_t N>
3914
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
3915
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
3916
+ returnable-element<range_reference_t<V>, N>
3917
  class elements_view : public view_interface<elements_view<V, N>> {
3918
  public:
3919
+ elements_view() requires default_initializable<V> = default;
3920
  constexpr explicit elements_view(V base);
3921
 
3922
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3923
  constexpr V base() && { return std::move(base_); }
3924
 
3925
  constexpr auto begin() requires (!simple-view<V>)
3926
  { return iterator<false>(ranges::begin(base_)); }
3927
 
3928
+ constexpr auto begin() const requires range<const V>
3929
  { return iterator<true>(ranges::begin(base_)); }
3930
 
3931
+ constexpr auto end() requires (!simple-view<V> && !common_range<V>)
3932
  { return sentinel<false>{ranges::end(base_)}; }
3933
 
3934
+ constexpr auto end() requires (!simple-view<V> && common_range<V>)
3935
  { return iterator<false>{ranges::end(base_)}; }
3936
 
3937
  constexpr auto end() const requires range<const V>
3938
  { return sentinel<true>{ranges::end(base_)}; }
3939
 
 
3946
  constexpr auto size() const requires sized_range<const V>
3947
  { return ranges::size(base_); }
3948
 
3949
  private:
3950
  // [range.elements.iterator], class template elements_view::iterator
3951
+ template<bool> class iterator; // exposition only
3952
+
3953
  // [range.elements.sentinel], class template elements_view::sentinel
3954
+ template<bool> class sentinel; // exposition only
3955
+
3956
  V base_ = V(); // exposition only
3957
  };
3958
  }
3959
  ```
3960
 
 
3968
 
3969
  ``` cpp
3970
  namespace std::ranges {
3971
  template<input_range V, size_t N>
3972
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
3973
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
3974
+ returnable-element<range_reference_t<V>, N>
3975
  template<bool Const>
3976
+ class elements_view<V, N>::iterator {
3977
+ using Base = maybe-const<Const, V>; // exposition only
3978
+
3979
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
3980
+
3981
+ static constexpr decltype(auto) get-element(const iterator_t<Base>& i); // exposition only
3982
 
 
3983
  public:
3984
+ using iterator_concept = see below;
3985
+ using iterator_category = see below; // not always present
3986
  using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
3987
  using difference_type = range_difference_t<Base>;
3988
 
3989
+ iterator() requires default_initializable<iterator_t<Base>> = default;
3990
  constexpr explicit iterator(iterator_t<Base> current);
3991
  constexpr iterator(iterator<!Const> i)
3992
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
3993
 
3994
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
3995
  constexpr iterator_t<Base> base() &&;
3996
 
3997
  constexpr decltype(auto) operator*() const
3998
+ { return get-element(current_); }
3999
 
4000
  constexpr iterator& operator++();
4001
+ constexpr void operator++(int);
4002
  constexpr iterator operator++(int) requires forward_range<Base>;
4003
 
4004
  constexpr iterator& operator--() requires bidirectional_range<Base>;
4005
  constexpr iterator operator--(int) requires bidirectional_range<Base>;
4006
 
 
4009
  constexpr iterator& operator-=(difference_type x)
4010
  requires random_access_range<Base>;
4011
 
4012
  constexpr decltype(auto) operator[](difference_type n) const
4013
  requires random_access_range<Base>
4014
+ { return get-element(current_ + n); }
4015
 
4016
  friend constexpr bool operator==(const iterator& x, const iterator& y)
4017
  requires equality_comparable<iterator_t<Base>>;
4018
 
4019
  friend constexpr bool operator<(const iterator& x, const iterator& y)
4020
  requires random_access_range<Base>;
4021
  friend constexpr bool operator>(const iterator& x, const iterator& y)
4022
  requires random_access_range<Base>;
4023
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
4024
  requires random_access_range<Base>;
4025
  friend constexpr bool operator>=(const iterator& x, const iterator& y)
4026
  requires random_access_range<Base>;
4027
  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
4028
  requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
 
4032
  friend constexpr iterator operator+(difference_type x, const iterator& y)
4033
  requires random_access_range<Base>;
4034
  friend constexpr iterator operator-(const iterator& x, difference_type y)
4035
  requires random_access_range<Base>;
4036
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4037
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
4038
  };
4039
  }
4040
  ```
4041
 
4042
+ The member *typedef-name* `iterator_concept` is defined as follows:
4043
+
4044
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
4045
+ denotes `random_access_iterator_tag`.
4046
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
4047
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
4048
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
4049
+ denotes `forward_iterator_tag`.
4050
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
4051
+
4052
+ The member *typedef-name* `iterator_category` is defined if and only if
4053
+ *`Base`* models `forward_range`. In that case, `iterator_category` is
4054
+ defined as follows: Let `C` denote the type
4055
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
4056
+
4057
+ - If `std::get<N>(*current_)` is an rvalue, `iterator_category` denotes
4058
+ `input_iterator_tag`.
4059
+ - Otherwise, if `C` models `derived_from<random_access_iterator_tag>`,
4060
+ `iterator_category` denotes `random_access_iterator_tag`.
4061
+ - Otherwise, `iterator_category` denotes `C`.
4062
+
4063
+ ``` cpp
4064
+ static constexpr decltype(auto) get-element(const iterator_t<Base>& i);
4065
+ ```
4066
+
4067
+ *Effects:* Equivalent to:
4068
+
4069
+ ``` cpp
4070
+ if constexpr (is_reference_v<range_reference_t<Base>>) {
4071
+ return std::get<N>(*i);
4072
+ } else {
4073
+ using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>;
4074
+ return static_cast<E>(std::get<N>(*i));
4075
+ }
4076
+ ```
4077
+
4078
  ``` cpp
4079
  constexpr explicit iterator(iterator_t<Base> current);
4080
  ```
4081
 
4082
  *Effects:* Initializes *current\_* with `std::move(current)`.
 
4087
  ```
4088
 
4089
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
4090
 
4091
  ``` cpp
4092
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
4093
  ```
4094
 
4095
  *Effects:* Equivalent to: `return `*`current_`*`;`
4096
 
4097
  ``` cpp
 
4110
  ++current_;
4111
  return *this;
4112
  ```
4113
 
4114
  ``` cpp
4115
+ constexpr void operator++(int);
4116
  ```
4117
 
4118
  *Effects:* Equivalent to: `++`*`current_`*.
4119
 
4120
  ``` cpp
 
4151
  --current_;
4152
  return temp;
4153
  ```
4154
 
4155
  ``` cpp
4156
+ constexpr iterator& operator+=(difference_type n)
4157
  requires random_access_range<Base>;
4158
  ```
4159
 
4160
  *Effects:* Equivalent to:
4161
 
 
4222
  ``` cpp
4223
  friend constexpr iterator operator+(const iterator& x, difference_type y)
4224
  requires random_access_range<Base>;
4225
  ```
4226
 
4227
+ *Effects:* Equivalent to: `return `*`iterator`*`{x} += y;`
4228
 
4229
  ``` cpp
4230
  friend constexpr iterator operator+(difference_type x, const iterator& y)
4231
  requires random_access_range<Base>;
4232
  ```
4233
 
4234
  *Effects:* Equivalent to: `return y + x;`
4235
 
4236
  ``` cpp
4237
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
4238
  requires random_access_range<Base>;
4239
  ```
4240
 
4241
+ *Effects:* Equivalent to: `return `*`iterator`*`{x} -= y;`
4242
 
4243
  ``` cpp
4244
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4245
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
4246
  ```
4247
 
4248
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
4249
 
4250
  #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
4251
 
4252
  ``` cpp
4253
  namespace std::ranges {
4254
  template<input_range V, size_t N>
4255
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
4256
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
4257
+ returnable-element<range_reference_t<V>, N>
4258
  template<bool Const>
4259
+ class elements_view<V, N>::sentinel {
4260
  private:
4261
+ using Base = maybe-const<Const, V>; // exposition only
4262
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
4263
+
4264
  public:
4265
  sentinel() = default;
4266
  constexpr explicit sentinel(sentinel_t<Base> end);
4267
  constexpr sentinel(sentinel<!Const> other)
4268
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4269
 
4270
  constexpr sentinel_t<Base> base() const;
4271
 
4272
+ template<bool OtherConst>
4273
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4274
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
4275
 
4276
+ template<bool OtherConst>
4277
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4278
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4279
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
4280
 
4281
+ template<bool OtherConst>
4282
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4283
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4284
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
4285
  };
4286
  }
4287
  ```
4288
 
4289
  ``` cpp
 
4304
  ```
4305
 
4306
  *Effects:* Equivalent to: `return `*`end_`*`;`
4307
 
4308
  ``` cpp
4309
+ template<bool OtherConst>
4310
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4311
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
4312
  ```
4313
 
4314
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
4315
 
4316
  ``` cpp
4317
+ template<bool OtherConst>
4318
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4319
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4320
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
4321
  ```
4322
 
4323
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
4324
 
4325
  ``` cpp
4326
+ template<bool OtherConst>
4327
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4328
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4329
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
4330
+ ```
4331
+
4332
+ *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
4333
+
4334
+ ### Enumerate view <a id="range.enumerate">[[range.enumerate]]</a>
4335
+
4336
+ #### Overview <a id="range.enumerate.overview">[[range.enumerate.overview]]</a>
4337
+
4338
+ `enumerate_view` is a view whose elements represent both the position
4339
+ and value from a sequence of elements.
4340
+
4341
+ The name `views::enumerate` denotes a range adaptor object. Given a
4342
+ subexpression `E`, the expression `views::enumerate(E)` is
4343
+ expression-equivalent to
4344
+ `enumerate_view<views::all_t<decltype((E))>>(E)`.
4345
+
4346
+ [*Example 1*:
4347
+
4348
+ ``` cpp
4349
+ vector<int> vec{ 1, 2, 3 };
4350
+ for (auto [index, value] : views::enumerate(vec))
4351
+ cout << index << ":" << value << ' '; // prints 0:1 1:2 2:3
4352
+ ```
4353
+
4354
+ — *end example*]
4355
+
4356
+ #### Class template `enumerate_view` <a id="range.enumerate.view">[[range.enumerate.view]]</a>
4357
+
4358
+ ``` cpp
4359
+ namespace std::ranges {
4360
+ template<view V>
4361
+ requires range-with-movable-references<V>
4362
+ class enumerate_view : public view_interface<enumerate_view<V>> {
4363
+ V base_ = V(); // exposition only
4364
+
4365
+ // [range.enumerate.iterator], class template enumerate_view::iterator
4366
+ template<bool Const>
4367
+ class iterator; // exposition only
4368
+
4369
+ // [range.enumerate.sentinel], class template enumerate_view::sentinel
4370
+ template<bool Const>
4371
+ class sentinel; // exposition only
4372
+
4373
+ public:
4374
+ constexpr enumerate_view() requires default_initializable<V> = default;
4375
+ constexpr explicit enumerate_view(V base);
4376
+
4377
+ constexpr auto begin() requires (!simple-view<V>)
4378
+ { return iterator<false>(ranges::begin(base_), 0); }
4379
+ constexpr auto begin() const requires range-with-movable-references<const V>
4380
+ { return iterator<true>(ranges::begin(base_), 0); }
4381
+
4382
+ constexpr auto end() requires (!simple-view<V>) {
4383
+ if constexpr (common_range<V> && sized_range<V>)
4384
+ return iterator<false>(ranges::end(base_), ranges::distance(base_));
4385
+ else
4386
+ return sentinel<false>(ranges::end(base_));
4387
+ }
4388
+ constexpr auto end() const requires range-with-movable-references<const V> {
4389
+ if constexpr (common_range<const V> && sized_range<const V>)
4390
+ return iterator<true>(ranges::end(base_), ranges::distance(base_));
4391
+ else
4392
+ return sentinel<true>(ranges::end(base_));
4393
+ }
4394
+
4395
+ constexpr auto size() requires sized_range<V>
4396
+ { return ranges::size(base_); }
4397
+ constexpr auto size() const requires sized_range<const V>
4398
+ { return ranges::size(base_); }
4399
+
4400
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
4401
+ constexpr V base() && { return std::move(base_); }
4402
+ };
4403
+
4404
+ template<class R>
4405
+ enumerate_view(R&&) -> enumerate_view<views::all_t<R>>;
4406
+ }
4407
+ ```
4408
+
4409
+ ``` cpp
4410
+ constexpr explicit enumerate_view(V base);
4411
+ ```
4412
+
4413
+ *Effects:* Initializes *base\_* with `std::move(base)`.
4414
+
4415
+ #### Class template `enumerate_view::iterator` <a id="range.enumerate.iterator">[[range.enumerate.iterator]]</a>
4416
+
4417
+ ``` cpp
4418
+ namespace std::ranges {
4419
+ template<view V>
4420
+ requires range-with-movable-references<V>
4421
+ template<bool Const>
4422
+ class enumerate_view<V>::iterator {
4423
+ using Base = maybe-const<Const, V>; // exposition only
4424
+
4425
+ public:
4426
+ using iterator_category = input_iterator_tag;
4427
+ using iterator_concept = see below;
4428
+ using difference_type = range_difference_t<Base>;
4429
+ using value_type = tuple<difference_type, range_value_t<Base>>;
4430
+
4431
+ private:
4432
+ using reference-type = // exposition only
4433
+ tuple<difference_type, range_reference_t<Base>>;
4434
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
4435
+ difference_type pos_ = 0; // exposition only
4436
+
4437
+ constexpr explicit
4438
+ iterator(iterator_t<Base> current, difference_type pos); // exposition only
4439
+
4440
+ public:
4441
+ iterator() requires default_initializable<iterator_t<Base>> = default;
4442
+ constexpr iterator(iterator<!Const> i)
4443
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4444
+
4445
+ constexpr const iterator_t<Base>& base() const & noexcept;
4446
+ constexpr iterator_t<Base> base() &&;
4447
+
4448
+ constexpr difference_type index() const noexcept;
4449
+
4450
+ constexpr auto operator*() const {
4451
+ return reference-type(pos_, *current_);
4452
+ }
4453
+
4454
+ constexpr iterator& operator++();
4455
+ constexpr void operator++(int);
4456
+ constexpr iterator operator++(int) requires forward_range<Base>;
4457
+
4458
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
4459
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
4460
+
4461
+ constexpr iterator& operator+=(difference_type x)
4462
+ requires random_access_range<Base>;
4463
+ constexpr iterator& operator-=(difference_type x)
4464
+ requires random_access_range<Base>;
4465
+
4466
+ constexpr auto operator[](difference_type n) const
4467
+ requires random_access_range<Base>
4468
+ { return reference-type(pos_ + n, current_[n]); }
4469
+
4470
+ friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept;
4471
+ friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept;
4472
+
4473
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
4474
+ requires random_access_range<Base>;
4475
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
4476
+ requires random_access_range<Base>;
4477
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
4478
+ requires random_access_range<Base>;
4479
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y);
4480
+
4481
+ friend constexpr auto iter_move(const iterator& i)
4482
+ noexcept(noexcept(ranges::iter_move(i.current_)) &&
4483
+ is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>) {
4484
+ return tuple<difference_type,
4485
+ range_rvalue_reference_t<Base>>(i.pos_, ranges::iter_move(i.current_));
4486
+ }
4487
+ };
4488
+ }
4489
+ ```
4490
+
4491
+ The member *typedef-name* `iterator::iterator_concept` is defined as
4492
+ follows:
4493
+
4494
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
4495
+ denotes `random_access_iterator_tag`.
4496
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
4497
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
4498
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
4499
+ denotes `forward_iterator_tag`.
4500
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
4501
+
4502
+ ``` cpp
4503
+ constexpr explicit iterator(iterator_t<Base> current, difference_type pos);
4504
+ ```
4505
+
4506
+ *Effects:* Initializes *current\_* with `std::move(current)` and *pos\_*
4507
+ with `pos`.
4508
+
4509
+ ``` cpp
4510
+ constexpr iterator(iterator<!Const> i)
4511
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4512
+ ```
4513
+
4514
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
4515
+ and *pos\_* with `i.`*`pos_`*.
4516
+
4517
+ ``` cpp
4518
+ constexpr const iterator_t<Base>& base() const & noexcept;
4519
+ ```
4520
+
4521
+ *Effects:* Equivalent to: `return `*`current_`*`;`
4522
+
4523
+ ``` cpp
4524
+ constexpr iterator_t<Base> base() &&;
4525
+ ```
4526
+
4527
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
4528
+
4529
+ ``` cpp
4530
+ constexpr difference_type index() const noexcept;
4531
+ ```
4532
+
4533
+ *Effects:* Equivalent to: `return `*`pos_`*`;`
4534
+
4535
+ ``` cpp
4536
+ constexpr iterator& operator++();
4537
+ ```
4538
+
4539
+ *Effects:* Equivalent to:
4540
+
4541
+ ``` cpp
4542
+ ++current_;
4543
+ ++pos_;
4544
+ return *this;
4545
+ ```
4546
+
4547
+ ``` cpp
4548
+ constexpr void operator++(int);
4549
+ ```
4550
+
4551
+ *Effects:* Equivalent to `++*this`.
4552
+
4553
+ ``` cpp
4554
+ constexpr iterator operator++(int) requires forward_range<Base>;
4555
+ ```
4556
+
4557
+ *Effects:* Equivalent to:
4558
+
4559
+ ``` cpp
4560
+ auto temp = *this;
4561
+ ++*this;
4562
+ return temp;
4563
+ ```
4564
+
4565
+ ``` cpp
4566
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
4567
+ ```
4568
+
4569
+ *Effects:* Equivalent to:
4570
+
4571
+ ``` cpp
4572
+ --current_;
4573
+ --pos_;
4574
+ return *this;
4575
+ ```
4576
+
4577
+ ``` cpp
4578
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
4579
+ ```
4580
+
4581
+ *Effects:* Equivalent to:
4582
+
4583
+ ``` cpp
4584
+ auto temp = *this;
4585
+ --*this;
4586
+ return temp;
4587
+ ```
4588
+
4589
+ ``` cpp
4590
+ constexpr iterator& operator+=(difference_type n)
4591
+ requires random_access_range<Base>;
4592
+ ```
4593
+
4594
+ *Effects:* Equivalent to:
4595
+
4596
+ ``` cpp
4597
+ current_ += n;
4598
+ pos_ += n;
4599
+ return *this;
4600
+ ```
4601
+
4602
+ ``` cpp
4603
+ constexpr iterator& operator-=(difference_type n)
4604
+ requires random_access_range<Base>;
4605
+ ```
4606
+
4607
+ *Effects:* Equivalent to:
4608
+
4609
+ ``` cpp
4610
+ current_ -= n;
4611
+ pos_ -= n;
4612
+ return *this;
4613
+ ```
4614
+
4615
+ ``` cpp
4616
+ friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept;
4617
+ ```
4618
+
4619
+ *Effects:* Equivalent to: `return x.`*`pos_`*` == y.`*`pos_`*`;`
4620
+
4621
+ ``` cpp
4622
+ friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept;
4623
+ ```
4624
+
4625
+ *Effects:* Equivalent to: `return x.`*`pos_`*` <=> y.`*`pos_`*`;`
4626
+
4627
+ ``` cpp
4628
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
4629
+ requires random_access_range<Base>;
4630
+ ```
4631
+
4632
+ *Effects:* Equivalent to:
4633
+
4634
+ ``` cpp
4635
+ auto temp = x;
4636
+ temp += y;
4637
+ return temp;
4638
+ ```
4639
+
4640
+ ``` cpp
4641
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
4642
+ requires random_access_range<Base>;
4643
+ ```
4644
+
4645
+ *Effects:* Equivalent to: `return y + x;`
4646
+
4647
+ ``` cpp
4648
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
4649
+ requires random_access_range<Base>;
4650
+ ```
4651
+
4652
+ *Effects:* Equivalent to:
4653
+
4654
+ ``` cpp
4655
+ auto temp = x;
4656
+ temp -= y;
4657
+ return temp;
4658
+ ```
4659
+
4660
+ ``` cpp
4661
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y);
4662
+ ```
4663
+
4664
+ *Effects:* Equivalent to: `return x.`*`pos_`*` - y.`*`pos_`*`;`
4665
+
4666
+ #### Class template `enumerate_view::sentinel` <a id="range.enumerate.sentinel">[[range.enumerate.sentinel]]</a>
4667
+
4668
+ ``` cpp
4669
+ namespace std::ranges {
4670
+ template<view V>
4671
+ requires range-with-movable-references<V>
4672
+ template<bool Const>
4673
+ class enumerate_view<V>::sentinel {
4674
+ using Base = maybe-const<Const, V>; // exposition only
4675
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
4676
+ constexpr explicit sentinel(sentinel_t<Base> end); // exposition only
4677
+
4678
+ public:
4679
+ sentinel() = default;
4680
+ constexpr sentinel(sentinel<!Const> other)
4681
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4682
+
4683
+ constexpr sentinel_t<Base> base() const;
4684
+
4685
+ template<bool OtherConst>
4686
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4687
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
4688
+
4689
+ template<bool OtherConst>
4690
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4691
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4692
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
4693
+
4694
+ template<bool OtherConst>
4695
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4696
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4697
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
4698
+ };
4699
+ }
4700
+ ```
4701
+
4702
+ ``` cpp
4703
+ constexpr explicit sentinel(sentinel_t<Base> end);
4704
+ ```
4705
+
4706
+ *Effects:* Initializes *end\_* with `std::move(end)`.
4707
+
4708
+ ``` cpp
4709
+ constexpr sentinel(sentinel<!Const> other)
4710
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4711
+ ```
4712
+
4713
+ *Effects:* Initializes *end\_* with `std::move(other.`*`end_`*`)`.
4714
+
4715
+ ``` cpp
4716
+ constexpr sentinel_t<Base> base() const;
4717
+ ```
4718
+
4719
+ *Effects:* Equivalent to: `return `*`end_`*`;`
4720
+
4721
+ ``` cpp
4722
+ template<bool OtherConst>
4723
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4724
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
4725
+ ```
4726
+
4727
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
4728
+
4729
+ ``` cpp
4730
+ template<bool OtherConst>
4731
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4732
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4733
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
4734
+ ```
4735
+
4736
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
4737
+
4738
+ ``` cpp
4739
+ template<bool OtherConst>
4740
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4741
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4742
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
4743
  ```
4744
 
4745
  *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
4746
 
4747
+ ### Zip view <a id="range.zip">[[range.zip]]</a>
4748
+
4749
+ #### Overview <a id="range.zip.overview">[[range.zip.overview]]</a>
4750
+
4751
+ `zip_view` takes any number of views and produces a view of tuples of
4752
+ references to the corresponding elements of the constituent views.
4753
+
4754
+ The name `views::zip` denotes a customization point object
4755
+ [[customization.point.object]]. Given a pack of subexpressions `Es...`,
4756
+ the expression `views::zip(Es...)` is expression-equivalent to
4757
+
4758
+ - `auto(views::empty<tuple<>>)` if `Es` is an empty pack,
4759
+ - otherwise, `zip_view<views::all_t<decltype((Es))>...>(Es...)`.
4760
+
4761
+ [*Example 1*:
4762
+
4763
+ ``` cpp
4764
+ vector v = {1, 2};
4765
+ list l = {'a', 'b', 'c'};
4766
+
4767
+ auto z = views::zip(v, l);
4768
+ range_reference_t<decltype(z)> f = z.front(); // f is a tuple<int&, char&>
4769
+ // that refers to the first element of v and l
4770
+
4771
+ for (auto&& [x, y] : z) {
4772
+ cout << '(' << x << ", " << y << ") "; // prints (1, a) (2, b)
4773
+ }
4774
+ ```
4775
+
4776
+ *end example*]
4777
+
4778
+ #### Class template `zip_view` <a id="range.zip.view">[[range.zip.view]]</a>
4779
+
4780
+ ``` cpp
4781
+ namespace std::ranges {
4782
+ template<class... Rs>
4783
+ concept zip-is-common = // exposition only
4784
+ (sizeof...(Rs) == 1 && (common_range<Rs> && ...)) ||
4785
+ (!(bidirectional_range<Rs> && ...) && (common_range<Rs> && ...)) ||
4786
+ ((random_access_range<Rs> && ...) && (sized_range<Rs> && ...));
4787
+
4788
+ template<input_range... Views>
4789
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
4790
+ class zip_view : public view_interface<zip_view<Views...>> {
4791
+ tuple<Views...> views_; // exposition only
4792
+
4793
+ // [range.zip.iterator], class template zip_view::iterator
4794
+ template<bool> class iterator; // exposition only
4795
+
4796
+ // [range.zip.sentinel], class template zip_view::sentinel
4797
+ template<bool> class sentinel; // exposition only
4798
+
4799
+ public:
4800
+ zip_view() = default;
4801
+ constexpr explicit zip_view(Views... views);
4802
+
4803
+ constexpr auto begin() requires (!(simple-view<Views> && ...)) {
4804
+ return iterator<false>(tuple-transform(ranges::begin, views_));
4805
+ }
4806
+ constexpr auto begin() const requires (range<const Views> && ...) {
4807
+ return iterator<true>(tuple-transform(ranges::begin, views_));
4808
+ }
4809
+
4810
+ constexpr auto end() requires (!(simple-view<Views> && ...)) {
4811
+ if constexpr (!zip-is-common<Views...>) {
4812
+ return sentinel<false>(tuple-transform(ranges::end, views_));
4813
+ } else if constexpr ((random_access_range<Views> && ...)) {
4814
+ return begin() + iter_difference_t<iterator<false>>(size());
4815
+ } else {
4816
+ return iterator<false>(tuple-transform(ranges::end, views_));
4817
+ }
4818
+ }
4819
+
4820
+ constexpr auto end() const requires (range<const Views> && ...) {
4821
+ if constexpr (!zip-is-common<const Views...>) {
4822
+ return sentinel<true>(tuple-transform(ranges::end, views_));
4823
+ } else if constexpr ((random_access_range<const Views> && ...)) {
4824
+ return begin() + iter_difference_t<iterator<true>>(size());
4825
+ } else {
4826
+ return iterator<true>(tuple-transform(ranges::end, views_));
4827
+ }
4828
+ }
4829
+
4830
+ constexpr auto size() requires (sized_range<Views> && ...);
4831
+ constexpr auto size() const requires (sized_range<const Views> && ...);
4832
+ };
4833
+
4834
+ template<class... Rs>
4835
+ zip_view(Rs&&...) -> zip_view<views::all_t<Rs>...>;
4836
+ }
4837
+ ```
4838
+
4839
+ Two `zip_view` objects have the same underlying sequence if and only if
4840
+ the corresponding elements of *`views_`* are equal [[concepts.equality]]
4841
+ and have the same underlying sequence.
4842
+
4843
+ [*Note 1*: In particular, comparison of iterators obtained from
4844
+ `zip_view` objects that do not have the same underlying sequence is not
4845
+ required to produce meaningful results
4846
+ [[iterator.concept.forward]]. — *end note*]
4847
+
4848
+ ``` cpp
4849
+ constexpr explicit zip_view(Views... views);
4850
+ ```
4851
+
4852
+ *Effects:* Initializes *views\_* with `std::move(views)...`.
4853
+
4854
+ ``` cpp
4855
+ constexpr auto size() requires (sized_range<Views> && ...);
4856
+ constexpr auto size() const requires (sized_range<const Views> && ...);
4857
+ ```
4858
+
4859
+ *Effects:* Equivalent to:
4860
+
4861
+ ``` cpp
4862
+ return apply([](auto... sizes) {
4863
+ using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>;
4864
+ return ranges::min({CT(sizes)...});
4865
+ }, tuple-transform(ranges::size, views_));
4866
+ ```
4867
+
4868
+ #### Class template `zip_view::iterator` <a id="range.zip.iterator">[[range.zip.iterator]]</a>
4869
+
4870
+ ``` cpp
4871
+ namespace std::ranges {
4872
+ template<bool Const, class... Views>
4873
+ concept all-random-access = // exposition only
4874
+ (random_access_range<maybe-const<Const, Views>> && ...);
4875
+ template<bool Const, class... Views>
4876
+ concept all-bidirectional = // exposition only
4877
+ (bidirectional_range<maybe-const<Const, Views>> && ...);
4878
+ template<bool Const, class... Views>
4879
+ concept all-forward = // exposition only
4880
+ (forward_range<maybe-const<Const, Views>> && ...);
4881
+
4882
+ template<input_range... Views>
4883
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
4884
+ template<bool Const>
4885
+ class zip_view<Views...>::iterator {
4886
+ tuple<iterator_t<maybe-const<Const, Views>>...> current_; // exposition only
4887
+ constexpr explicit iterator(tuple<iterator_t<maybe-const<Const, Views>>...>);
4888
+ // exposition only
4889
+ public:
4890
+ using iterator_category = input_iterator_tag; // not always present
4891
+ using iterator_concept = see below;
4892
+ using value_type = tuple<range_value_t<maybe-const<Const, Views>>...>;
4893
+ using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>;
4894
+
4895
+ iterator() = default;
4896
+ constexpr iterator(iterator<!Const> i)
4897
+ requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
4898
+
4899
+ constexpr auto operator*() const;
4900
+ constexpr iterator& operator++();
4901
+ constexpr void operator++(int);
4902
+ constexpr iterator operator++(int) requires all-forward<Const, Views...>;
4903
+
4904
+ constexpr iterator& operator--() requires all-bidirectional<Const, Views...>;
4905
+ constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>;
4906
+
4907
+ constexpr iterator& operator+=(difference_type x)
4908
+ requires all-random-access<Const, Views...>;
4909
+ constexpr iterator& operator-=(difference_type x)
4910
+ requires all-random-access<Const, Views...>;
4911
+
4912
+ constexpr auto operator[](difference_type n) const
4913
+ requires all-random-access<Const, Views...>;
4914
+
4915
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
4916
+ requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
4917
+
4918
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
4919
+ requires all-random-access<Const, Views...>;
4920
+
4921
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
4922
+ requires all-random-access<Const, Views...>;
4923
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
4924
+ requires all-random-access<Const, Views...>;
4925
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
4926
+ requires all-random-access<Const, Views...>;
4927
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4928
+ requires (sized_sentinel_for<iterator_t<maybe-const<Const, Views>>,
4929
+ iterator_t<maybe-const<Const, Views>>> && ...);
4930
+
4931
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
4932
+
4933
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
4934
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...);
4935
+ };
4936
+ }
4937
+ ```
4938
+
4939
+ `iterator::iterator_concept` is defined as follows:
4940
+
4941
+ - If `all-random-access<Const, Views...>` is modeled, then
4942
+ `iterator_concept` denotes `random_access_iterator_tag`.
4943
+ - Otherwise, if `all-bidirectional<Const, Views...>` is modeled, then
4944
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
4945
+ - Otherwise, if `all-forward<Const, Views...>` is modeled, then
4946
+ `iterator_concept` denotes `forward_iterator_tag`.
4947
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
4948
+
4949
+ `iterator::iterator_category` is present if and only if
4950
+ `all-forward<Const, Views...>` is modeled.
4951
+
4952
+ If the invocation of any non-const member function of *`iterator`* exits
4953
+ via an exception, the iterator acquires a singular value.
4954
+
4955
+ ``` cpp
4956
+ constexpr explicit iterator(tuple<iterator_t<maybe-const<Const, Views>>...> current);
4957
+ ```
4958
+
4959
+ *Effects:* Initializes *current\_* with `std::move(current)`.
4960
+
4961
+ ``` cpp
4962
+ constexpr iterator(iterator<!Const> i)
4963
+ requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
4964
+ ```
4965
+
4966
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
4967
+
4968
+ ``` cpp
4969
+ constexpr auto operator*() const;
4970
+ ```
4971
+
4972
+ *Effects:* Equivalent to:
4973
+
4974
+ ``` cpp
4975
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
4976
+ ```
4977
+
4978
+ ``` cpp
4979
+ constexpr iterator& operator++();
4980
+ ```
4981
+
4982
+ *Effects:* Equivalent to:
4983
+
4984
+ ``` cpp
4985
+ tuple-for-each([](auto& i) { ++i; }, current_);
4986
+ return *this;
4987
+ ```
4988
+
4989
+ ``` cpp
4990
+ constexpr void operator++(int);
4991
+ ```
4992
+
4993
+ *Effects:* Equivalent to `++*this`.
4994
+
4995
+ ``` cpp
4996
+ constexpr iterator operator++(int) requires all-forward<Const, Views...>;
4997
+ ```
4998
+
4999
+ *Effects:* Equivalent to:
5000
+
5001
+ ``` cpp
5002
+ auto tmp = *this;
5003
+ ++*this;
5004
+ return tmp;
5005
+ ```
5006
+
5007
+ ``` cpp
5008
+ constexpr iterator& operator--() requires all-bidirectional<Const, Views...>;
5009
+ ```
5010
+
5011
+ *Effects:* Equivalent to:
5012
+
5013
+ ``` cpp
5014
+ tuple-for-each([](auto& i) { --i; }, current_);
5015
+ return *this;
5016
+ ```
5017
+
5018
+ ``` cpp
5019
+ constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>;
5020
+ ```
5021
+
5022
+ *Effects:* Equivalent to:
5023
+
5024
+ ``` cpp
5025
+ auto tmp = *this;
5026
+ --*this;
5027
+ return tmp;
5028
+ ```
5029
+
5030
+ ``` cpp
5031
+ constexpr iterator& operator+=(difference_type x)
5032
+ requires all-random-access<Const, Views...>;
5033
+ ```
5034
+
5035
+ *Effects:* Equivalent to:
5036
+
5037
+ ``` cpp
5038
+ tuple-for-each([&]<class I>(I& i) { i += iter_difference_t<I>(x); }, current_);
5039
+ return *this;
5040
+ ```
5041
+
5042
+ ``` cpp
5043
+ constexpr iterator& operator-=(difference_type x)
5044
+ requires all-random-access<Const, Views...>;
5045
+ ```
5046
+
5047
+ *Effects:* Equivalent to:
5048
+
5049
+ ``` cpp
5050
+ tuple-for-each([&]<class I>(I& i) { i -= iter_difference_t<I>(x); }, current_);
5051
+ return *this;
5052
+ ```
5053
+
5054
+ ``` cpp
5055
+ constexpr auto operator[](difference_type n) const
5056
+ requires all-random-access<Const, Views...>;
5057
+ ```
5058
+
5059
+ *Effects:* Equivalent to:
5060
+
5061
+ ``` cpp
5062
+ return tuple-transform([&]<class I>(I& i) -> decltype(auto) {
5063
+ return i[iter_difference_t<I>(n)];
5064
+ }, current_);
5065
+ ```
5066
+
5067
+ ``` cpp
5068
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
5069
+ requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
5070
+ ```
5071
+
5072
+ *Returns:*
5073
+
5074
+ - `x.`*`current_`*` == y.`*`current_`* if
5075
+ `all-bidirectional<Const, Views...>` is `true`.
5076
+ - Otherwise, `true` if there exists an integer
5077
+ 0 ≤ i < `sizeof...(Views)` such that
5078
+ `bool(std::get<`i`>(x.`*`current_`*`) == std::get<`i`>(y.`*`current_`*`))`
5079
+ is `true`. \[*Note 1*: This allows `zip_view` to model `common_range`
5080
+ when all constituent views model `common_range`. — *end note*]
5081
+ - Otherwise, `false`.
5082
+
5083
+ ``` cpp
5084
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
5085
+ requires all-random-access<Const, Views...>;
5086
+ ```
5087
+
5088
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
5089
+
5090
+ ``` cpp
5091
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
5092
+ requires all-random-access<Const, Views...>;
5093
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
5094
+ requires all-random-access<Const, Views...>;
5095
+ ```
5096
+
5097
+ *Effects:* Equivalent to:
5098
+
5099
+ ``` cpp
5100
+ auto r = i;
5101
+ r += n;
5102
+ return r;
5103
+ ```
5104
+
5105
+ ``` cpp
5106
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
5107
+ requires all-random-access<Const, Views...>;
5108
+ ```
5109
+
5110
+ *Effects:* Equivalent to:
5111
+
5112
+ ``` cpp
5113
+ auto r = i;
5114
+ r -= n;
5115
+ return r;
5116
+ ```
5117
+
5118
+ ``` cpp
5119
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
5120
+ requires (sized_sentinel_for<iterator_t<maybe-const<Const, Views>>,
5121
+ iterator_t<maybe-const<Const, Views>>> && ...);
5122
+ ```
5123
+
5124
+ Let *`DIST`*`(`i`)` be
5125
+ `difference_type(std::get<`i`>(x.`*`current_`*`) - std::get<`i`>(y.`*`current_`*`))`.
5126
+
5127
+ *Returns:* The value with the smallest absolute value among
5128
+ *`DIST`*`(`n`)` for all integers 0 ≤ n < `sizeof...(Views)`.
5129
+
5130
+ ``` cpp
5131
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
5132
+ ```
5133
+
5134
+ *Effects:* Equivalent to:
5135
+
5136
+ ``` cpp
5137
+ return tuple-transform(ranges::iter_move, i.current_);
5138
+ ```
5139
+
5140
+ *Remarks:* The exception specification is equivalent to:
5141
+
5142
+ ``` cpp
5143
+ (noexcept(ranges::iter_move(declval<const iterator_t<maybe-const<Const,
5144
+ Views>>&>())) && ...) &&
5145
+ (is_nothrow_move_constructible_v<range_rvalue_reference_t<maybe-const<Const,
5146
+ Views>>> && ...)
5147
+ ```
5148
+
5149
+ ``` cpp
5150
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
5151
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...);
5152
+ ```
5153
+
5154
+ *Effects:* For every integer 0 ≤ i < `sizeof...(Views)`, performs:
5155
+
5156
+ ``` cpp
5157
+ ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
5158
+ ```
5159
+
5160
+ *Remarks:* The exception specification is equivalent to the logical of
5161
+ the following expressions:
5162
+
5163
+ ``` cpp
5164
+ noexcept(ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_)))
5165
+ ```
5166
+
5167
+ for every integer 0 ≤ i < `sizeof...(Views)`.
5168
+
5169
+ #### Class template `zip_view::sentinel` <a id="range.zip.sentinel">[[range.zip.sentinel]]</a>
5170
+
5171
+ ``` cpp
5172
+ namespace std::ranges {
5173
+ template<input_range... Views>
5174
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
5175
+ template<bool Const>
5176
+ class zip_view<Views...>::sentinel {
5177
+ tuple<sentinel_t<maybe-const<Const, Views>>...> end_; // exposition only
5178
+ constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> end);
5179
+ // exposition only
5180
+ public:
5181
+ sentinel() = default;
5182
+ constexpr sentinel(sentinel<!Const> i)
5183
+ requires Const && (convertible_to<sentinel_t<Views>, sentinel_t<const Views>> && ...);
5184
+
5185
+ template<bool OtherConst>
5186
+ requires (sentinel_for<sentinel_t<maybe-const<Const, Views>>,
5187
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
5188
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5189
+
5190
+ template<bool OtherConst>
5191
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
5192
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
5193
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
5194
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
5195
+
5196
+ template<bool OtherConst>
5197
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
5198
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
5199
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
5200
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
5201
+ };
5202
+ }
5203
+ ```
5204
+
5205
+ ``` cpp
5206
+ constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> end);
5207
+ ```
5208
+
5209
+ *Effects:* Initializes *end\_* with `end`.
5210
+
5211
+ ``` cpp
5212
+ constexpr sentinel(sentinel<!Const> i)
5213
+ requires Const && (convertible_to<sentinel_t<Views>, sentinel_t<const Views>> && ...);
5214
+ ```
5215
+
5216
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
5217
+
5218
+ ``` cpp
5219
+ template<bool OtherConst>
5220
+ requires (sentinel_for<sentinel_t<maybe-const<Const, Views>>,
5221
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
5222
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5223
+ ```
5224
+
5225
+ *Returns:* `true` if there exists an integer 0 ≤ i < `sizeof...(Views)`
5226
+ such that
5227
+ `bool(std::get<`i`>(x.`*`current_`*`) == std::get<`i`>(y.`*`end_`*`))`
5228
+ is `true`. Otherwise, `false`.
5229
+
5230
+ ``` cpp
5231
+ template<bool OtherConst>
5232
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
5233
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
5234
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
5235
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
5236
+ ```
5237
+
5238
+ Let `D` be the return type. Let *`DIST`*`(`i`)` be
5239
+ `D(std::get<`i`>(x.`*`current_`*`) - std::get<`i`>(y.`*`end_`*`))`.
5240
+
5241
+ *Returns:* The value with the smallest absolute value among
5242
+ *`DIST`*`(`n`)` for all integers 0 ≤ n < `sizeof...(Views)`.
5243
+
5244
+ ``` cpp
5245
+ template<bool OtherConst>
5246
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
5247
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
5248
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
5249
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
5250
+ ```
5251
+
5252
+ *Effects:* Equivalent to `return -(x - y);`
5253
+
5254
+ ### Zip transform view <a id="range.zip.transform">[[range.zip.transform]]</a>
5255
+
5256
+ #### Overview <a id="range.zip.transform.overview">[[range.zip.transform.overview]]</a>
5257
+
5258
+ `zip_transform_view` takes an invocable object and any number of views
5259
+ and produces a view whose Mᵗʰ element is the result of applying the
5260
+ invocable object to the Mᵗʰ elements of all views.
5261
+
5262
+ The name `views::zip_transform` denotes a customization point object
5263
+ [[customization.point.object]]. Let `F` be a subexpression, and let
5264
+ `Es...` be a pack of subexpressions.
5265
+
5266
+ - If `Es` is an empty pack, let `FD` be `decay_t<decltype((F))>`.
5267
+ - If `move_constructible<FD> &&
5268
+ regular_invocable<FD&>` is `false`, or if
5269
+ `decay_t<invoke_result_t<FD&>>` is not an object type,
5270
+ `views::zip_transform(F, Es...)` is ill-formed.
5271
+ - Otherwise, the expression `views::zip_transform(F, Es...)` is
5272
+ expression-equivalent to
5273
+ ``` cpp
5274
+ ((void)F, auto(views::empty<decay_t<invoke_result_t<FD&>>>))
5275
+ ```
5276
+ - Otherwise, the expression `views::zip_transform(F, Es...)` is
5277
+ expression-equivalent to `zip_transform_view(F, Es...)`.
5278
+
5279
+ [*Example 1*:
5280
+
5281
+ ``` cpp
5282
+ vector v1 = {1, 2};
5283
+ vector v2 = {4, 5, 6};
5284
+
5285
+ for (auto i : views::zip_transform(plus(), v1, v2)) {
5286
+ cout << i << ' '; // prints 5 7
5287
+ }
5288
+ ```
5289
+
5290
+ — *end example*]
5291
+
5292
+ #### Class template `zip_transform_view` <a id="range.zip.transform.view">[[range.zip.transform.view]]</a>
5293
+
5294
+ ``` cpp
5295
+ namespace std::ranges {
5296
+ template<move_constructible F, input_range... Views>
5297
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
5298
+ regular_invocable<F&, range_reference_t<Views>...> &&
5299
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
5300
+ class zip_transform_view : public view_interface<zip_transform_view<F, Views...>> {
5301
+ movable-box<F> fun_; // exposition only
5302
+ zip_view<Views...> zip_; // exposition only
5303
+
5304
+ using InnerView = zip_view<Views...>; // exposition only
5305
+ template<bool Const>
5306
+ using ziperator = iterator_t<maybe-const<Const, InnerView>>; // exposition only
5307
+ template<bool Const>
5308
+ using zentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only
5309
+
5310
+ // [range.zip.transform.iterator], class template zip_transform_view::iterator
5311
+ template<bool> class iterator; // exposition only
5312
+
5313
+ // [range.zip.transform.sentinel], class template zip_transform_view::sentinel
5314
+ template<bool> class sentinel; // exposition only
5315
+
5316
+ public:
5317
+ zip_transform_view() = default;
5318
+
5319
+ constexpr explicit zip_transform_view(F fun, Views... views);
5320
+
5321
+ constexpr auto begin() { return iterator<false>(*this, zip_.begin()); }
5322
+
5323
+ constexpr auto begin() const
5324
+ requires range<const InnerView> &&
5325
+ regular_invocable<const F&, range_reference_t<const Views>...> {
5326
+ return iterator<true>(*this, zip_.begin());
5327
+ }
5328
+
5329
+ constexpr auto end() {
5330
+ if constexpr (common_range<InnerView>) {
5331
+ return iterator<false>(*this, zip_.end());
5332
+ } else {
5333
+ return sentinel<false>(zip_.end());
5334
+ }
5335
+ }
5336
+
5337
+ constexpr auto end() const
5338
+ requires range<const InnerView> &&
5339
+ regular_invocable<const F&, range_reference_t<const Views>...> {
5340
+ if constexpr (common_range<const InnerView>) {
5341
+ return iterator<true>(*this, zip_.end());
5342
+ } else {
5343
+ return sentinel<true>(zip_.end());
5344
+ }
5345
+ }
5346
+
5347
+ constexpr auto size() requires sized_range<InnerView> {
5348
+ return zip_.size();
5349
+ }
5350
+
5351
+ constexpr auto size() const requires sized_range<const InnerView> {
5352
+ return zip_.size();
5353
+ }
5354
+ };
5355
+
5356
+ template<class F, class... Rs>
5357
+ zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>;
5358
+ }
5359
+ ```
5360
+
5361
+ ``` cpp
5362
+ constexpr explicit zip_transform_view(F fun, Views... views);
5363
+ ```
5364
+
5365
+ *Effects:* Initializes *fun\_* with `std::move(fun)` and *zip\_* with
5366
+ `std::move(views)...`.
5367
+
5368
+ #### Class template `zip_transform_view::iterator` <a id="range.zip.transform.iterator">[[range.zip.transform.iterator]]</a>
5369
+
5370
+ ``` cpp
5371
+ namespace std::ranges {
5372
+ template<move_constructible F, input_range... Views>
5373
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
5374
+ regular_invocable<F&, range_reference_t<Views>...> &&
5375
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
5376
+ template<bool Const>
5377
+ class zip_transform_view<F, Views...>::iterator {
5378
+ using Parent = maybe-const<Const, zip_transform_view>; // exposition only
5379
+ using Base = maybe-const<Const, InnerView>; // exposition only
5380
+ Parent* parent_ = nullptr; // exposition only
5381
+ ziperator<Const> inner_; // exposition only
5382
+
5383
+ constexpr iterator(Parent& parent, ziperator<Const> inner); // exposition only
5384
+
5385
+ public:
5386
+ using iterator_category = see belownc; // not always present
5387
+ using iterator_concept = typename ziperator<Const>::iterator_concept;
5388
+ using value_type =
5389
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
5390
+ range_reference_t<maybe-const<Const, Views>>...>>;
5391
+ using difference_type = range_difference_t<Base>;
5392
+
5393
+ iterator() = default;
5394
+ constexpr iterator(iterator<!Const> i)
5395
+ requires Const && convertible_to<ziperator<false>, ziperator<Const>>;
5396
+
5397
+ constexpr decltype(auto) operator*() const noexcept(see below);
5398
+ constexpr iterator& operator++();
5399
+ constexpr void operator++(int);
5400
+ constexpr iterator operator++(int) requires forward_range<Base>;
5401
+
5402
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
5403
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
5404
+
5405
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
5406
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
5407
+
5408
+ constexpr decltype(auto) operator[](difference_type n) const
5409
+ requires random_access_range<Base>;
5410
+
5411
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
5412
+ requires equality_comparable<ziperator<Const>>;
5413
+
5414
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
5415
+ requires random_access_range<Base>;
5416
+
5417
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
5418
+ requires random_access_range<Base>;
5419
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
5420
+ requires random_access_range<Base>;
5421
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
5422
+ requires random_access_range<Base>;
5423
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
5424
+ requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>;
5425
+ };
5426
+ }
5427
+ ```
5428
+
5429
+ The member *typedef-name* `iterator::iterator_category` is defined if
5430
+ and only if *`Base`* models `forward_range`. In that case,
5431
+ `iterator::iterator_category` is defined as follows:
5432
+
5433
+ - If
5434
+ ``` cpp
5435
+ invoke_result_t<maybe-const<Const, F>&, range_reference_t<maybe-const<Const, Views>>...>
5436
+ ```
5437
+
5438
+ is not a reference, `iterator_category` denotes `input_iterator_tag`.
5439
+ - Otherwise, let `Cs` denote the pack of types
5440
+ `iterator_traits<iterator_t<maybe-const<Const, Views>>>::iterator_category...`.
5441
+ - If `(derived_from<Cs, random_access_iterator_tag> && ...)` is
5442
+ `true`, `iterator_category` denotes `random_access_iterator_tag`.
5443
+ - Otherwise, if
5444
+ `(derived_from<Cs, bidirectional_iterator_tag> && ...)` is `true`,
5445
+ `iterator_category` denotes `bidirectional_iterator_tag`.
5446
+ - Otherwise, if `(derived_from<Cs, forward_iterator_tag> && ...)` is
5447
+ `true`, `iterator_category` denotes `forward_iterator_tag`.
5448
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
5449
+
5450
+ ``` cpp
5451
+ constexpr iterator(Parent& parent, ziperator<Const> inner);
5452
+ ```
5453
+
5454
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and *inner\_*
5455
+ with `std::move(inner)`.
5456
+
5457
+ ``` cpp
5458
+ constexpr iterator(iterator<!Const> i)
5459
+ requires Const && convertible_to<ziperator<false>, ziperator<Const>>;
5460
+ ```
5461
+
5462
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *inner\_*
5463
+ with `std::move(i.`*`inner_`*`)`.
5464
+
5465
+ ``` cpp
5466
+ constexpr decltype(auto) operator*() const noexcept(see below);
5467
+ ```
5468
+
5469
+ *Effects:* Equivalent to:
5470
+
5471
+ ``` cpp
5472
+ return apply([&](const auto&... iters) -> decltype(auto) {
5473
+ return invoke(*parent_->fun_, *iters...);
5474
+ }, inner_.current_);
5475
+ ```
5476
+
5477
+ *Remarks:* Let `Is` be the pack `0, 1, …, ``(sizeof...(Views)-1)`. The
5478
+ exception specification is equivalent to:
5479
+ `noexcept(invoke(*`*`parent_`*`->`*`fun_`*`, *std::get<Is>(`*`inner_`*`.`*`current_`*`)...))`.
5480
+
5481
+ ``` cpp
5482
+ constexpr iterator& operator++();
5483
+ ```
5484
+
5485
+ *Effects:* Equivalent to:
5486
+
5487
+ ``` cpp
5488
+ ++inner_;
5489
+ return *this;
5490
+ ```
5491
+
5492
+ ``` cpp
5493
+ constexpr void operator++(int);
5494
+ ```
5495
+
5496
+ *Effects:* Equivalent to: `++*this`.
5497
+
5498
+ ``` cpp
5499
+ constexpr iterator operator++(int) requires forward_range<Base>;
5500
+ ```
5501
+
5502
+ *Effects:* Equivalent to:
5503
+
5504
+ ``` cpp
5505
+ auto tmp = *this;
5506
+ ++*this;
5507
+ return tmp;
5508
+ ```
5509
+
5510
+ ``` cpp
5511
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
5512
+ ```
5513
+
5514
+ *Effects:* Equivalent to:
5515
+
5516
+ ``` cpp
5517
+ --inner_;
5518
+ return *this;
5519
+ ```
5520
+
5521
+ ``` cpp
5522
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
5523
+ ```
5524
+
5525
+ *Effects:* Equivalent to:
5526
+
5527
+ ``` cpp
5528
+ auto tmp = *this;
5529
+ --*this;
5530
+ return tmp;
5531
+ ```
5532
+
5533
+ ``` cpp
5534
+ constexpr iterator& operator+=(difference_type x)
5535
+ requires random_access_range<Base>;
5536
+ ```
5537
+
5538
+ *Effects:* Equivalent to:
5539
+
5540
+ ``` cpp
5541
+ inner_ += x;
5542
+ return *this;
5543
+ ```
5544
+
5545
+ ``` cpp
5546
+ constexpr iterator& operator-=(difference_type x)
5547
+ requires random_access_range<Base>;
5548
+ ```
5549
+
5550
+ *Effects:* Equivalent to:
5551
+
5552
+ ``` cpp
5553
+ inner_ -= x;
5554
+ return *this;
5555
+ ```
5556
+
5557
+ ``` cpp
5558
+ constexpr decltype(auto) operator[](difference_type n) const
5559
+ requires random_access_range<Base>;
5560
+ ```
5561
+
5562
+ *Effects:* Equivalent to:
5563
+
5564
+ ``` cpp
5565
+ return apply([&]<class... Is>(const Is&... iters) -> decltype(auto) {
5566
+ return invoke(*parent_->fun_, iters[iter_difference_t<Is>(n)]...);
5567
+ }, inner_.current_);
5568
+ ```
5569
+
5570
+ ``` cpp
5571
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
5572
+ requires equality_comparable<ziperator<Const>>;
5573
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
5574
+ requires random_access_range<Base>;
5575
+ ```
5576
+
5577
+ Let *op* be the operator.
5578
+
5579
+ *Effects:* Equivalent to:
5580
+ `return x.`*`inner_`*` `*`op`*` y.`*`inner_`*`;`
5581
+
5582
+ ``` cpp
5583
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
5584
+ requires random_access_range<Base>;
5585
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
5586
+ requires random_access_range<Base>;
5587
+ ```
5588
+
5589
+ *Effects:* Equivalent to:
5590
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` + n);`
5591
+
5592
+ ``` cpp
5593
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
5594
+ requires random_access_range<Base>;
5595
+ ```
5596
+
5597
+ *Effects:* Equivalent to:
5598
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` - n);`
5599
+
5600
+ ``` cpp
5601
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
5602
+ requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>;
5603
+ ```
5604
+
5605
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
5606
+
5607
+ #### Class template `zip_transform_view::sentinel` <a id="range.zip.transform.sentinel">[[range.zip.transform.sentinel]]</a>
5608
+
5609
+ ``` cpp
5610
+ namespace std::ranges {
5611
+ template<move_constructible F, input_range... Views>
5612
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
5613
+ regular_invocable<F&, range_reference_t<Views>...> &&
5614
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
5615
+ template<bool Const>
5616
+ class zip_transform_view<F, Views...>::sentinel {
5617
+ zentinel<Const> inner_; // exposition only
5618
+ constexpr explicit sentinel(zentinel<Const> inner); // exposition only
5619
+
5620
+ public:
5621
+ sentinel() = default;
5622
+ constexpr sentinel(sentinel<!Const> i)
5623
+ requires Const && convertible_to<zentinel<false>, zentinel<Const>>;
5624
+
5625
+ template<bool OtherConst>
5626
+ requires sentinel_for<zentinel<Const>, ziperator<OtherConst>>
5627
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5628
+
5629
+ template<bool OtherConst>
5630
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
5631
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
5632
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
5633
+
5634
+ template<bool OtherConst>
5635
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
5636
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
5637
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
5638
+ };
5639
+ }
5640
+ ```
5641
+
5642
+ ``` cpp
5643
+ constexpr explicit sentinel(zentinel<Const> inner);
5644
+ ```
5645
+
5646
+ *Effects:* Initializes *inner\_* with `inner`.
5647
+
5648
+ ``` cpp
5649
+ constexpr sentinel(sentinel<!Const> i)
5650
+ requires Const && convertible_to<zentinel<false>, zentinel<Const>>;
5651
+ ```
5652
+
5653
+ *Effects:* Initializes *inner\_* with `std::move(i.`*`inner_`*`)`.
5654
+
5655
+ ``` cpp
5656
+ template<bool OtherConst>
5657
+ requires sentinel_for<zentinel<Const>, ziperator<OtherConst>>
5658
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5659
+ ```
5660
+
5661
+ *Effects:* Equivalent to: `return x.`*`inner_`*` == y.`*`inner_`*`;`
5662
+
5663
+ ``` cpp
5664
+ template<bool OtherConst>
5665
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
5666
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
5667
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
5668
+ template<bool OtherConst>
5669
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
5670
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
5671
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
5672
+ ```
5673
+
5674
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
5675
+
5676
+ ### Adjacent view <a id="range.adjacent">[[range.adjacent]]</a>
5677
+
5678
+ #### Overview <a id="range.adjacent.overview">[[range.adjacent.overview]]</a>
5679
+
5680
+ `adjacent_view` takes a view and produces a view whose Mᵗʰ element is a
5681
+ tuple of references to the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
5682
+ original view. If the original view has fewer than N elements, the
5683
+ resulting view is empty.
5684
+
5685
+ The name `views::adjacent<N>` denotes a range adaptor object
5686
+ [[range.adaptor.object]]. Given a subexpression `E` and a constant
5687
+ expression `N`, the expression `views::adjacent<N>(E)` is
5688
+ expression-equivalent to
5689
+
5690
+ - `((void)E, auto(views::empty<tuple<>>))` if `N` is equal to `0`,
5691
+ - otherwise, `adjacent_view<views::all_t<decltype((E))>, N>(E)`.
5692
+
5693
+ [*Example 1*:
5694
+
5695
+ ``` cpp
5696
+ vector v = {1, 2, 3, 4};
5697
+
5698
+ for (auto i : v | views::adjacent<2>) {
5699
+ cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints (1, 2) (2, 3) (3, 4)
5700
+ }
5701
+ ```
5702
+
5703
+ — *end example*]
5704
+
5705
+ Define `REPEAT(T, N)` as a pack of `N` types, each of which denotes the
5706
+ same type as `T`.
5707
+
5708
+ #### Class template `adjacent_view` <a id="range.adjacent.view">[[range.adjacent.view]]</a>
5709
+
5710
+ ``` cpp
5711
+ namespace std::ranges {
5712
+ template<forward_range V, size_t N>
5713
+ requires view<V> && (N > 0)
5714
+ class adjacent_view : public view_interface<adjacent_view<V, N>> {
5715
+ V base_ = V(); // exposition only
5716
+
5717
+ // [range.adjacent.iterator], class template adjacent_view::iterator
5718
+ template<bool> class iterator; // exposition only
5719
+
5720
+ // [range.adjacent.sentinel], class template adjacent_view::sentinel
5721
+ template<bool> class sentinel; // exposition only
5722
+
5723
+ struct as-sentinel{}; // exposition only
5724
+
5725
+ public:
5726
+ adjacent_view() requires default_initializable<V> = default;
5727
+ constexpr explicit adjacent_view(V base);
5728
+
5729
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
5730
+ constexpr V base() && { return std::move(base_); }
5731
+
5732
+ constexpr auto begin() requires (!simple-view<V>) {
5733
+ return iterator<false>(ranges::begin(base_), ranges::end(base_));
5734
+ }
5735
+
5736
+ constexpr auto begin() const requires range<const V> {
5737
+ return iterator<true>(ranges::begin(base_), ranges::end(base_));
5738
+ }
5739
+
5740
+ constexpr auto end() requires (!simple-view<V>) {
5741
+ if constexpr (common_range<V>) {
5742
+ return iterator<false>(as-sentinel{}, ranges::begin(base_), ranges::end(base_));
5743
+ } else {
5744
+ return sentinel<false>(ranges::end(base_));
5745
+ }
5746
+ }
5747
+
5748
+ constexpr auto end() const requires range<const V> {
5749
+ if constexpr (common_range<const V>) {
5750
+ return iterator<true>(as-sentinel{}, ranges::begin(base_), ranges::end(base_));
5751
+ } else {
5752
+ return sentinel<true>(ranges::end(base_));
5753
+ }
5754
+ }
5755
+
5756
+ constexpr auto size() requires sized_range<V>;
5757
+ constexpr auto size() const requires sized_range<const V>;
5758
+ };
5759
+ }
5760
+ ```
5761
+
5762
+ ``` cpp
5763
+ constexpr explicit adjacent_view(V base);
5764
+ ```
5765
+
5766
+ *Effects:* Initializes *base\_* with `std::move(base)`.
5767
+
5768
+ ``` cpp
5769
+ constexpr auto size() requires sized_range<V>;
5770
+ constexpr auto size() const requires sized_range<const V>;
5771
+ ```
5772
+
5773
+ *Effects:* Equivalent to:
5774
+
5775
+ ``` cpp
5776
+ using ST = decltype(ranges::size(base_));
5777
+ using CT = common_type_t<ST, size_t>;
5778
+ auto sz = static_cast<CT>(ranges::size(base_));
5779
+ sz -= std::min<CT>(sz, N - 1);
5780
+ return static_cast<ST>(sz);
5781
+ ```
5782
+
5783
+ #### Class template `adjacent_view::iterator` <a id="range.adjacent.iterator">[[range.adjacent.iterator]]</a>
5784
+
5785
+ ``` cpp
5786
+ namespace std::ranges {
5787
+ template<forward_range V, size_t N>
5788
+ requires view<V> && (N > 0)
5789
+ template<bool Const>
5790
+ class adjacent_view<V, N>::iterator {
5791
+ using Base = maybe-const<Const, V>; // exposition only
5792
+ array<iterator_t<Base>, N> current_ = array<iterator_t<Base>, N>(); // exposition only
5793
+ constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last); // exposition only
5794
+ constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
5795
+ // exposition only
5796
+ public:
5797
+ using iterator_category = input_iterator_tag;
5798
+ using iterator_concept = see below;
5799
+ using value_type = tuple<REPEAT(range_value_t<Base>, N)...>;
5800
+ using difference_type = range_difference_t<Base>;
5801
+
5802
+ iterator() = default;
5803
+ constexpr iterator(iterator<!Const> i)
5804
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
5805
+
5806
+ constexpr auto operator*() const;
5807
+ constexpr iterator& operator++();
5808
+ constexpr iterator operator++(int);
5809
+
5810
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
5811
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
5812
+
5813
+ constexpr iterator& operator+=(difference_type x)
5814
+ requires random_access_range<Base>;
5815
+ constexpr iterator& operator-=(difference_type x)
5816
+ requires random_access_range<Base>;
5817
+
5818
+ constexpr auto operator[](difference_type n) const
5819
+ requires random_access_range<Base>;
5820
+
5821
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
5822
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
5823
+ requires random_access_range<Base>;
5824
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
5825
+ requires random_access_range<Base>;
5826
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
5827
+ requires random_access_range<Base>;
5828
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
5829
+ requires random_access_range<Base>;
5830
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
5831
+ requires random_access_range<Base> &&
5832
+ three_way_comparable<iterator_t<Base>>;
5833
+
5834
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
5835
+ requires random_access_range<Base>;
5836
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
5837
+ requires random_access_range<Base>;
5838
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
5839
+ requires random_access_range<Base>;
5840
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
5841
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
5842
+
5843
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
5844
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
5845
+ requires indirectly_swappable<iterator_t<Base>>;
5846
+ };
5847
+ }
5848
+ ```
5849
+
5850
+ `iterator::iterator_concept` is defined as follows:
5851
+
5852
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
5853
+ denotes `random_access_iterator_tag`.
5854
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
5855
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
5856
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
5857
+
5858
+ If the invocation of any non-const member function of *`iterator`* exits
5859
+ via an exception, the *`iterator`* acquires a singular value.
5860
+
5861
+ ``` cpp
5862
+ constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last);
5863
+ ```
5864
+
5865
+ *Ensures:* *`current_`*`[0] == first` is `true`, and for every integer
5866
+ 1 ≤ i < `N`,
5867
+ *`current_`*`[`i`] == ranges::next(`*`current_`*`[`i`-1], 1, last)` is
5868
+ `true`.
5869
+
5870
+ ``` cpp
5871
+ constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
5872
+ ```
5873
+
5874
+ *Ensures:* If *Base* does not model `bidirectional_range`, each element
5875
+ of *current\_* is equal to *last*. Otherwise,
5876
+ *`current_`*`[N-1] == last` is `true`, and for every integer
5877
+ 0 ≤ i < (`N` - 1),
5878
+ *`current_`*`[`i`] == ranges::prev(`*`current_`*`[`i`+1], 1, first)` is
5879
+ `true`.
5880
+
5881
+ ``` cpp
5882
+ constexpr iterator(iterator<!Const> i)
5883
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
5884
+ ```
5885
+
5886
+ *Effects:* Initializes each element of *current\_* with the
5887
+ corresponding element of `i.`*`current_`* as an xvalue.
5888
+
5889
+ ``` cpp
5890
+ constexpr auto operator*() const;
5891
+ ```
5892
+
5893
+ *Effects:* Equivalent to:
5894
+
5895
+ ``` cpp
5896
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
5897
+ ```
5898
+
5899
+ ``` cpp
5900
+ constexpr iterator& operator++();
5901
+ ```
5902
+
5903
+ *Preconditions:* *`current_`*`.back()` is incrementable.
5904
+
5905
+ *Ensures:* Each element of *current\_* is equal to `ranges::next(i)`,
5906
+ where `i` is the value of that element before the call.
5907
+
5908
+ *Returns:* `*this`.
5909
+
5910
+ ``` cpp
5911
+ constexpr iterator operator++(int);
5912
+ ```
5913
+
5914
+ *Effects:* Equivalent to:
5915
+
5916
+ ``` cpp
5917
+ auto tmp = *this;
5918
+ ++*this;
5919
+ return tmp;
5920
+ ```
5921
+
5922
+ ``` cpp
5923
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
5924
+ ```
5925
+
5926
+ *Preconditions:* *`current_`*`.front()` is decrementable.
5927
+
5928
+ *Ensures:* Each element of *current\_* is equal to `ranges::prev(i)`,
5929
+ where `i` is the value of that element before the call.
5930
+
5931
+ *Returns:* `*this`.
5932
+
5933
+ ``` cpp
5934
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
5935
+ ```
5936
+
5937
+ *Effects:* Equivalent to:
5938
+
5939
+ ``` cpp
5940
+ auto tmp = *this;
5941
+ --*this;
5942
+ return tmp;
5943
+ ```
5944
+
5945
+ ``` cpp
5946
+ constexpr iterator& operator+=(difference_type x)
5947
+ requires random_access_range<Base>;
5948
+ ```
5949
+
5950
+ *Preconditions:* *`current_`*`.back() + x` has well-defined behavior.
5951
+
5952
+ *Ensures:* Each element of *current\_* is equal to `i + x`, where `i` is
5953
+ the value of that element before the call.
5954
+
5955
+ *Returns:* `*this`.
5956
+
5957
+ ``` cpp
5958
+ constexpr iterator& operator-=(difference_type x)
5959
+ requires random_access_range<Base>;
5960
+ ```
5961
+
5962
+ *Preconditions:* *`current_`*`.front() - x` has well-defined behavior.
5963
+
5964
+ *Ensures:* Each element of *current\_* is equal to `i - x`, where `i` is
5965
+ the value of that element before the call.
5966
+
5967
+ *Returns:* `*this`.
5968
+
5969
+ ``` cpp
5970
+ constexpr auto operator[](difference_type n) const
5971
+ requires random_access_range<Base>;
5972
+ ```
5973
+
5974
+ *Effects:* Equivalent to:
5975
+
5976
+ ``` cpp
5977
+ return tuple-transform([&](auto& i) -> decltype(auto) { return i[n]; }, current_);
5978
+ ```
5979
+
5980
+ ``` cpp
5981
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
5982
+ ```
5983
+
5984
+ *Returns:* `x.`*`current_`*`.back() == y.`*`current_`*`.back()`.
5985
+
5986
+ ``` cpp
5987
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
5988
+ requires random_access_range<Base>;
5989
+ ```
5990
+
5991
+ *Returns:* `x.`*`current_`*`.back() < y.`*`current_`*`.back()`.
5992
+
5993
+ ``` cpp
5994
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
5995
+ requires random_access_range<Base>;
5996
+ ```
5997
+
5998
+ *Effects:* Equivalent to: `return y < x;`
5999
+
6000
+ ``` cpp
6001
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
6002
+ requires random_access_range<Base>;
6003
+ ```
6004
+
6005
+ *Effects:* Equivalent to: `return !(y < x);`
6006
+
6007
+ ``` cpp
6008
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
6009
+ requires random_access_range<Base>;
6010
+ ```
6011
+
6012
+ *Effects:* Equivalent to: `return !(x < y);`
6013
+
6014
+ ``` cpp
6015
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
6016
+ requires random_access_range<Base> &&
6017
+ three_way_comparable<iterator_t<Base>>;
6018
+ ```
6019
+
6020
+ *Returns:* `x.`*`current_`*`.back() <=> y.`*`current_`*`.back()`.
6021
+
6022
+ ``` cpp
6023
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
6024
+ requires random_access_range<Base>;
6025
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
6026
+ requires random_access_range<Base>;
6027
+ ```
6028
+
6029
+ *Effects:* Equivalent to:
6030
+
6031
+ ``` cpp
6032
+ auto r = i;
6033
+ r += n;
6034
+ return r;
6035
+ ```
6036
+
6037
+ ``` cpp
6038
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
6039
+ requires random_access_range<Base>;
6040
+ ```
6041
+
6042
+ *Effects:* Equivalent to:
6043
+
6044
+ ``` cpp
6045
+ auto r = i;
6046
+ r -= n;
6047
+ return r;
6048
+ ```
6049
+
6050
+ ``` cpp
6051
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
6052
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
6053
+ ```
6054
+
6055
+ *Effects:* Equivalent to:
6056
+ `return x.`*`current_`*`.back() - y.`*`current_`*`.back();`
6057
+
6058
+ ``` cpp
6059
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
6060
+ ```
6061
+
6062
+ *Effects:* Equivalent to:
6063
+ `return `*`tuple-transform`*`(ranges::iter_move, i.`*`current_`*`);`
6064
+
6065
+ *Remarks:* The exception specification is equivalent to:
6066
+
6067
+ ``` cpp
6068
+ noexcept(ranges::iter_move(declval<const iterator_t<Base>&>())) &&
6069
+ is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>
6070
+ ```
6071
+
6072
+ ``` cpp
6073
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
6074
+ requires indirectly_swappable<iterator_t<Base>>;
6075
+ ```
6076
+
6077
+ *Preconditions:* None of the iterators in `l.`*`current_`* is equal to
6078
+ an iterator in `r.`*`current_`*.
6079
+
6080
+ *Effects:* For every integer 0 ≤ i < `N`, performs
6081
+ `ranges::iter_swap(l.`*`current_`*`[`i`], r.`*`current_`*`[`i`])`.
6082
+
6083
+ *Remarks:* The exception specification is equivalent to:
6084
+
6085
+ ``` cpp
6086
+ noexcept(ranges::iter_swap(declval<iterator_t<Base>>(), declval<iterator_t<Base>>()))
6087
+ ```
6088
+
6089
+ #### Class template `adjacent_view::sentinel` <a id="range.adjacent.sentinel">[[range.adjacent.sentinel]]</a>
6090
+
6091
+ ``` cpp
6092
+ namespace std::ranges {
6093
+ template<forward_range V, size_t N>
6094
+ requires view<V> && (N > 0)
6095
+ template<bool Const>
6096
+ class adjacent_view<V, N>::sentinel {
6097
+ using Base = maybe-const<Const, V>; // exposition only
6098
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
6099
+ constexpr explicit sentinel(sentinel_t<Base> end); // exposition only
6100
+
6101
+ public:
6102
+ sentinel() = default;
6103
+ constexpr sentinel(sentinel<!Const> i)
6104
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
6105
+
6106
+ template<bool OtherConst>
6107
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
6108
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
6109
+
6110
+ template<bool OtherConst>
6111
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
6112
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
6113
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
6114
+
6115
+ template<bool OtherConst>
6116
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
6117
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
6118
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
6119
+ };
6120
+ }
6121
+ ```
6122
+
6123
+ ``` cpp
6124
+ constexpr explicit sentinel(sentinel_t<Base> end);
6125
+ ```
6126
+
6127
+ *Effects:* Initializes *end\_* with `end`.
6128
+
6129
+ ``` cpp
6130
+ constexpr sentinel(sentinel<!Const> i)
6131
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
6132
+ ```
6133
+
6134
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
6135
+
6136
+ ``` cpp
6137
+ template<bool OtherConst>
6138
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
6139
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
6140
+ ```
6141
+
6142
+ *Effects:* Equivalent to:
6143
+ `return x.`*`current_`*`.back() == y.`*`end_`*`;`
6144
+
6145
+ ``` cpp
6146
+ template<bool OtherConst>
6147
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
6148
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
6149
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
6150
+ ```
6151
+
6152
+ *Effects:* Equivalent to:
6153
+ `return x.`*`current_`*`.back() - y.`*`end_`*`;`
6154
+
6155
+ ``` cpp
6156
+ template<bool OtherConst>
6157
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
6158
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
6159
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
6160
+ ```
6161
+
6162
+ *Effects:* Equivalent to:
6163
+ `return y.`*`end_`*` - x.`*`current_`*`.back();`
6164
+
6165
+ ### Adjacent transform view <a id="range.adjacent.transform">[[range.adjacent.transform]]</a>
6166
+
6167
+ #### Overview <a id="range.adjacent.transform.overview">[[range.adjacent.transform.overview]]</a>
6168
+
6169
+ `adjacent_transform_view` takes an invocable object and a view and
6170
+ produces a view whose Mᵗʰ element is the result of applying the
6171
+ invocable object to the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
6172
+ original view. If the original view has fewer than N elements, the
6173
+ resulting view is empty.
6174
+
6175
+ The name `views::adjacent_transform<N>` denotes a range adaptor object
6176
+ [[range.adaptor.object]]. Given subexpressions `E` and `F` and a
6177
+ constant expression `N`:
6178
+
6179
+ - If `N` is equal to `0`, `views::adjacent_transform<N>(E, F)` is
6180
+ expression-equivalent to `((void)E, views::zip_transform(F))`, except
6181
+ that the evaluations of `E` and `F` are indeterminately sequenced.
6182
+ - Otherwise, the expression `views::adjacent_transform<N>(E, F)` is
6183
+ expression-equivalent to
6184
+ `adjacent_transform_view<views::all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F)`.
6185
+
6186
+ [*Example 1*:
6187
+
6188
+ ``` cpp
6189
+ vector v = {1, 2, 3, 4};
6190
+
6191
+ for (auto i : v | views::adjacent_transform<2>(std::multiplies())) {
6192
+ cout << i << ' '; // prints 2 6 12
6193
+ }
6194
+ ```
6195
+
6196
+ — *end example*]
6197
+
6198
+ #### Class template `adjacent_transform_view` <a id="range.adjacent.transform.view">[[range.adjacent.transform.view]]</a>
6199
+
6200
+ ``` cpp
6201
+ namespace std::ranges {
6202
+ template<forward_range V, move_constructible F, size_t N>
6203
+ requires view<V> && (N > 0) && is_object_v<F> &&
6204
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
6205
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
6206
+ class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {
6207
+ movable-box<F> fun_; // exposition only
6208
+ adjacent_view<V, N> inner_; // exposition only
6209
+
6210
+ using InnerView = adjacent_view<V, N>; // exposition only
6211
+ template<bool Const>
6212
+ using inner-iterator = iterator_t<maybe-const<Const, InnerView>>; // exposition only
6213
+ template<bool Const>
6214
+ using inner-sentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only
6215
+
6216
+ // [range.adjacent.transform.iterator], class template adjacent_transform_view::iterator
6217
+ template<bool> class iterator; // exposition only
6218
+
6219
+ // [range.adjacent.transform.sentinel], class template adjacent_transform_view::sentinel
6220
+ template<bool> class sentinel; // exposition only
6221
+
6222
+ public:
6223
+ adjacent_transform_view() = default;
6224
+ constexpr explicit adjacent_transform_view(V base, F fun);
6225
+
6226
+ constexpr V base() const & requires copy_constructible<InnerView> { return inner_.base(); }
6227
+ constexpr V base() && { return std::move(inner_).base(); }
6228
+
6229
+ constexpr auto begin() {
6230
+ return iterator<false>(*this, inner_.begin());
6231
+ }
6232
+
6233
+ constexpr auto begin() const
6234
+ requires range<const InnerView> &&
6235
+ regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> {
6236
+ return iterator<true>(*this, inner_.begin());
6237
+ }
6238
+
6239
+ constexpr auto end() {
6240
+ if constexpr (common_range<InnerView>) {
6241
+ return iterator<false>(*this, inner_.end());
6242
+ } else {
6243
+ return sentinel<false>(inner_.end());
6244
+ }
6245
+ }
6246
+
6247
+ constexpr auto end() const
6248
+ requires range<const InnerView> &&
6249
+ regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> {
6250
+ if constexpr (common_range<const InnerView>) {
6251
+ return iterator<true>(*this, inner_.end());
6252
+ } else {
6253
+ return sentinel<true>(inner_.end());
6254
+ }
6255
+ }
6256
+
6257
+ constexpr auto size() requires sized_range<InnerView> {
6258
+ return inner_.size();
6259
+ }
6260
+
6261
+ constexpr auto size() const requires sized_range<const InnerView> {
6262
+ return inner_.size();
6263
+ }
6264
+ };
6265
+ }
6266
+ ```
6267
+
6268
+ ``` cpp
6269
+ constexpr explicit adjacent_transform_view(V base, F fun);
6270
+ ```
6271
+
6272
+ *Effects:* Initializes *fun\_* with `std::move(fun)` and *inner\_* with
6273
+ `std::move(base)`.
6274
+
6275
+ #### Class template `adjacent_transform_view::iterator` <a id="range.adjacent.transform.iterator">[[range.adjacent.transform.iterator]]</a>
6276
+
6277
+ ``` cpp
6278
+ namespace std::ranges {
6279
+ template<forward_range V, move_constructible F, size_t N>
6280
+ requires view<V> && (N > 0) && is_object_v<F> &&
6281
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
6282
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
6283
+ template<bool Const>
6284
+ class adjacent_transform_view<V, F, N>::iterator {
6285
+ using Parent = maybe-const<Const, adjacent_transform_view>; // exposition only
6286
+ using Base = maybe-const<Const, V>; // exposition only
6287
+ Parent* parent_ = nullptr; // exposition only
6288
+ inner-iterator<Const> inner_; // exposition only
6289
+
6290
+ constexpr iterator(Parent& parent, inner-iterator<Const> inner); // exposition only
6291
+
6292
+ public:
6293
+ using iterator_category = see below;
6294
+ using iterator_concept = typename inner-iterator<Const>::iterator_concept;
6295
+ using value_type =
6296
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
6297
+ REPEAT(range_reference_t<Base>, N)...>>;
6298
+ using difference_type = range_difference_t<Base>;
6299
+
6300
+ iterator() = default;
6301
+ constexpr iterator(iterator<!Const> i)
6302
+ requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
6303
+
6304
+ constexpr decltype(auto) operator*() const noexcept(see below);
6305
+ constexpr iterator& operator++();
6306
+ constexpr iterator operator++(int);
6307
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
6308
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
6309
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
6310
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
6311
+
6312
+ constexpr decltype(auto) operator[](difference_type n) const
6313
+ requires random_access_range<Base>;
6314
+
6315
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
6316
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
6317
+ requires random_access_range<Base>;
6318
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
6319
+ requires random_access_range<Base>;
6320
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
6321
+ requires random_access_range<Base>;
6322
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
6323
+ requires random_access_range<Base>;
6324
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
6325
+ requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
6326
+
6327
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
6328
+ requires random_access_range<Base>;
6329
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
6330
+ requires random_access_range<Base>;
6331
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
6332
+ requires random_access_range<Base>;
6333
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
6334
+ requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
6335
+ };
6336
+ }
6337
+ ```
6338
+
6339
+ The member *typedef-name* `iterator::iterator_category` is defined as
6340
+ follows:
6341
+
6342
+ - If `invoke_result_t<maybe-const<Const, F>&,
6343
+ REPEAT(range_reference_t<Base>, N)...>` isnot a reference,
6344
+ `iterator_category` denotes `input_iterator_tag`.
6345
+ - Otherwise, let `C` denote the type
6346
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
6347
+ - If `derived_from<C, random_access_iterator_tag>` is `true`,
6348
+ `iterator_category` denotes `random_access_iterator_tag`.
6349
+ - Otherwise, if `derived_from<C, bidirectional_iterator_tag>` is
6350
+ `true`, `iterator_category` denotes `bidirectional_iterator_tag`.
6351
+ - Otherwise, if `derived_from<C, forward_iterator_tag>` is `true`,
6352
+ `iterator_category` denotes `forward_iterator_tag`.
6353
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
6354
+
6355
+ ``` cpp
6356
+ constexpr iterator(Parent& parent, inner-iterator<Const> inner);
6357
+ ```
6358
+
6359
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and *inner\_*
6360
+ with `std::move(inner)`.
6361
+
6362
+ ``` cpp
6363
+ constexpr iterator(iterator<!Const> i)
6364
+ requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
6365
+ ```
6366
+
6367
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *inner\_*
6368
+ with `std::move(i.`*`inner_`*`)`.
6369
+
6370
+ ``` cpp
6371
+ constexpr decltype(auto) operator*() const noexcept(see below);
6372
+ ```
6373
+
6374
+ *Effects:* Equivalent to:
6375
+
6376
+ ``` cpp
6377
+ return apply([&](const auto&... iters) -> decltype(auto) {
6378
+ return invoke(*parent_->fun_, *iters...);
6379
+ }, inner_.current_);
6380
+ ```
6381
+
6382
+ *Remarks:* Let `Is` be the pack `0, 1, …, (N-1)`. The exception
6383
+ specification is equivalent to:
6384
+
6385
+ ``` cpp
6386
+ noexcept(invoke(*parent_->fun_, *std::get<Is>(inner_.current_)...))
6387
+ ```
6388
+
6389
+ ``` cpp
6390
+ constexpr iterator& operator++();
6391
+ ```
6392
+
6393
+ *Effects:* Equivalent to:
6394
+
6395
+ ``` cpp
6396
+ ++inner_;
6397
+ return *this;
6398
+ ```
6399
+
6400
+ ``` cpp
6401
+ constexpr iterator operator++(int);
6402
+ ```
6403
+
6404
+ *Effects:* Equivalent to:
6405
+
6406
+ ``` cpp
6407
+ auto tmp = *this;
6408
+ ++*this;
6409
+ return tmp;
6410
+ ```
6411
+
6412
+ ``` cpp
6413
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
6414
+ ```
6415
+
6416
+ *Effects:* Equivalent to:
6417
+
6418
+ ``` cpp
6419
+ --inner_;
6420
+ return *this;
6421
+ ```
6422
+
6423
+ ``` cpp
6424
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
6425
+ ```
6426
+
6427
+ *Effects:* Equivalent to:
6428
+
6429
+ ``` cpp
6430
+ auto tmp = *this;
6431
+ --*this;
6432
+ return tmp;
6433
+ ```
6434
+
6435
+ ``` cpp
6436
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
6437
+ ```
6438
+
6439
+ *Effects:* Equivalent to:
6440
+
6441
+ ``` cpp
6442
+ inner_ += x;
6443
+ return *this;
6444
+ ```
6445
+
6446
+ ``` cpp
6447
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
6448
+ ```
6449
+
6450
+ *Effects:* Equivalent to:
6451
+
6452
+ ``` cpp
6453
+ inner_ -= x;
6454
+ return *this;
6455
+ ```
6456
+
6457
+ ``` cpp
6458
+ constexpr decltype(auto) operator[](difference_type n) const
6459
+ requires random_access_range<Base>;
6460
+ ```
6461
+
6462
+ *Effects:* Equivalent to:
6463
+
6464
+ ``` cpp
6465
+ return apply([&](const auto&... iters) -> decltype(auto) {
6466
+ return invoke(*parent_->fun_, iters[n]...);
6467
+ }, inner_.current_);
6468
+ ```
6469
+
6470
+ ``` cpp
6471
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
6472
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
6473
+ requires random_access_range<Base>;
6474
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
6475
+ requires random_access_range<Base>;
6476
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
6477
+ requires random_access_range<Base>;
6478
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
6479
+ requires random_access_range<Base>;
6480
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
6481
+ requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
6482
+ ```
6483
+
6484
+ Let *op* be the operator.
6485
+
6486
+ *Effects:* Equivalent to:
6487
+ `return x.`*`inner_`*` `*`op`*` y.`*`inner_`*`;`
6488
+
6489
+ ``` cpp
6490
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
6491
+ requires random_access_range<Base>;
6492
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
6493
+ requires random_access_range<Base>;
6494
+ ```
6495
+
6496
+ *Effects:* Equivalent to:
6497
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` + n);`
6498
+
6499
+ ``` cpp
6500
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
6501
+ requires random_access_range<Base>;
6502
+ ```
6503
+
6504
+ *Effects:* Equivalent to:
6505
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` - n);`
6506
+
6507
+ ``` cpp
6508
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
6509
+ requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
6510
+ ```
6511
+
6512
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
6513
+
6514
+ #### Class template `adjacent_transform_view::sentinel` <a id="range.adjacent.transform.sentinel">[[range.adjacent.transform.sentinel]]</a>
6515
+
6516
+ ``` cpp
6517
+ namespace std::ranges {
6518
+ template<forward_range V, move_constructible F, size_t N>
6519
+ requires view<V> && (N > 0) && is_object_v<F> &&
6520
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
6521
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
6522
+ template<bool Const>
6523
+ class adjacent_transform_view<V, F, N>::sentinel {
6524
+ inner-sentinel<Const> inner_; // exposition only
6525
+ constexpr explicit sentinel(inner-sentinel<Const> inner); // exposition only
6526
+
6527
+ public:
6528
+ sentinel() = default;
6529
+ constexpr sentinel(sentinel<!Const> i)
6530
+ requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
6531
+
6532
+ template<bool OtherConst>
6533
+ requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6534
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
6535
+
6536
+ template<bool OtherConst>
6537
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6538
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
6539
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
6540
+
6541
+ template<bool OtherConst>
6542
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6543
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
6544
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
6545
+ };
6546
+ }
6547
+ ```
6548
+
6549
+ ``` cpp
6550
+ constexpr explicit sentinel(inner-sentinel<Const> inner);
6551
+ ```
6552
+
6553
+ *Effects:* Initializes *inner\_* with `inner`.
6554
+
6555
+ ``` cpp
6556
+ constexpr sentinel(sentinel<!Const> i)
6557
+ requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
6558
+ ```
6559
+
6560
+ *Effects:* Initializes *inner\_* with `std::move(i.`*`inner_`*`)`.
6561
+
6562
+ ``` cpp
6563
+ template<bool OtherConst>
6564
+ requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6565
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
6566
+ ```
6567
+
6568
+ *Effects:* Equivalent to `return x.`*`inner_`*` == y.`*`inner_`*`;`
6569
+
6570
+ ``` cpp
6571
+ template<bool OtherConst>
6572
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6573
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
6574
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
6575
+
6576
+ template<bool OtherConst>
6577
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6578
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
6579
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
6580
+ ```
6581
+
6582
+ *Effects:* Equivalent to `return x.`*`inner_`*` - y.`*`inner_`*`;`
6583
+
6584
+ ### Chunk view <a id="range.chunk">[[range.chunk]]</a>
6585
+
6586
+ #### Overview <a id="range.chunk.overview">[[range.chunk.overview]]</a>
6587
+
6588
+ `chunk_view` takes a view and a number N and produces a range of views
6589
+ that are N-sized non-overlapping successive chunks of the elements of
6590
+ the original view, in order. The last view in the range can have fewer
6591
+ than N elements.
6592
+
6593
+ The name `views::chunk` denotes a range adaptor object
6594
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
6595
+ expression `views::chunk(E, N)` is expression-equivalent to
6596
+ `chunk_view(E, N)`.
6597
+
6598
+ [*Example 1*:
6599
+
6600
+ ``` cpp
6601
+ vector v = {1, 2, 3, 4, 5};
6602
+
6603
+ for (auto r : v | views::chunk(2)) {
6604
+ cout << '[';
6605
+ auto sep = "";
6606
+ for (auto i : r) {
6607
+ cout << sep << i;
6608
+ sep = ", ";
6609
+ }
6610
+ cout << "] ";
6611
+ }
6612
+ // The above prints [1, 2] [3, 4] [5]
6613
+ ```
6614
+
6615
+ — *end example*]
6616
+
6617
+ #### Class template `chunk_view` for input ranges <a id="range.chunk.view.input">[[range.chunk.view.input]]</a>
6618
+
6619
+ ``` cpp
6620
+ namespace std::ranges {
6621
+ template<class I>
6622
+ constexpr I div-ceil(I num, I denom) { // exposition only
6623
+ I r = num / denom;
6624
+ if (num % denom)
6625
+ ++r;
6626
+ return r;
6627
+ }
6628
+
6629
+ template<view V>
6630
+ requires input_range<V>
6631
+ class chunk_view : public view_interface<chunk_view<V>> {
6632
+ V base_; // exposition only
6633
+ range_difference_t<V> n_; // exposition only
6634
+ range_difference_t<V> remainder_ = 0; // exposition only
6635
+
6636
+ non-propagating-cache<iterator_t<V>> current_; // exposition only
6637
+
6638
+ // [range.chunk.outer.iter], class chunk_view::outer-iterator
6639
+ class outer-iterator; // exposition only
6640
+
6641
+ // [range.chunk.inner.iter], class chunk_view::inner-iterator
6642
+ class inner-iterator; // exposition only
6643
+
6644
+ public:
6645
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
6646
+
6647
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
6648
+ constexpr V base() && { return std::move(base_); }
6649
+
6650
+ constexpr outer-iterator begin();
6651
+ constexpr default_sentinel_t end() const noexcept;
6652
+
6653
+ constexpr auto size() requires sized_range<V>;
6654
+ constexpr auto size() const requires sized_range<const V>;
6655
+ };
6656
+
6657
+ template<class R>
6658
+ chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;
6659
+ }
6660
+ ```
6661
+
6662
+ ``` cpp
6663
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
6664
+ ```
6665
+
6666
+ *Preconditions:* `n > 0` is `true`.
6667
+
6668
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
6669
+ `n`.
6670
+
6671
+ ``` cpp
6672
+ constexpr outer-iterator begin();
6673
+ ```
6674
+
6675
+ *Effects:* Equivalent to:
6676
+
6677
+ ``` cpp
6678
+ current_ = ranges::begin(base_);
6679
+ remainder_ = n_;
6680
+ return outer-iterator(*this);
6681
+ ```
6682
+
6683
+ ``` cpp
6684
+ constexpr default_sentinel_t end() const noexcept;
6685
+ ```
6686
+
6687
+ *Returns:* `default_sentinel`.
6688
+
6689
+ ``` cpp
6690
+ constexpr auto size() requires sized_range<V>;
6691
+ constexpr auto size() const requires sized_range<const V>;
6692
+ ```
6693
+
6694
+ *Effects:* Equivalent to:
6695
+
6696
+ ``` cpp
6697
+ return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
6698
+ ```
6699
+
6700
+ #### Class `chunk_view::outer-iterator` <a id="range.chunk.outer.iter">[[range.chunk.outer.iter]]</a>
6701
+
6702
+ ``` cpp
6703
+ namespace std::ranges {
6704
+ template<view V>
6705
+ requires input_range<V>
6706
+ class chunk_view<V>::outer-iterator {
6707
+ chunk_view* parent_; // exposition only
6708
+
6709
+ constexpr explicit outer-iterator(chunk_view& parent); // exposition only
6710
+
6711
+ public:
6712
+ using iterator_concept = input_iterator_tag;
6713
+ using difference_type = range_difference_t<V>;
6714
+
6715
+ // [range.chunk.outer.value], class chunk_view::outer-iterator::value_type
6716
+ struct value_type;
6717
+
6718
+ outer-iterator(outer-iterator&&) = default;
6719
+ outer-iterator& operator=(outer-iterator&&) = default;
6720
+
6721
+ constexpr value_type operator*() const;
6722
+ constexpr outer-iterator& operator++();
6723
+ constexpr void operator++(int);
6724
+
6725
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
6726
+
6727
+ friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)
6728
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6729
+ friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)
6730
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6731
+ };
6732
+ }
6733
+ ```
6734
+
6735
+ ``` cpp
6736
+ constexpr explicit outer-iterator(chunk_view& parent);
6737
+ ```
6738
+
6739
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
6740
+
6741
+ ``` cpp
6742
+ constexpr value_type operator*() const;
6743
+ ```
6744
+
6745
+ *Preconditions:* `*this == default_sentinel` is `false`.
6746
+
6747
+ *Returns:* `value_type(*`*`parent_`*`)`.
6748
+
6749
+ ``` cpp
6750
+ constexpr outer-iterator& operator++();
6751
+ ```
6752
+
6753
+ *Preconditions:* `*this == default_sentinel` is `false`.
6754
+
6755
+ *Effects:* Equivalent to:
6756
+
6757
+ ``` cpp
6758
+ ranges::advance(*parent_->current_, parent_->remainder_, ranges::end(parent_->base_));
6759
+ parent_->remainder_ = parent_->n_;
6760
+ return *this;
6761
+ ```
6762
+
6763
+ ``` cpp
6764
+ constexpr void operator++(int);
6765
+ ```
6766
+
6767
+ *Effects:* Equivalent to `++*this`.
6768
+
6769
+ ``` cpp
6770
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
6771
+ ```
6772
+
6773
+ *Effects:* Equivalent to:
6774
+
6775
+ ``` cpp
6776
+ return *x.parent_->current_ == ranges::end(x.parent_->base_) && x.parent_->remainder_ != 0;
6777
+ ```
6778
+
6779
+ ``` cpp
6780
+ friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)
6781
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6782
+ ```
6783
+
6784
+ *Effects:* Equivalent to:
6785
+
6786
+ ``` cpp
6787
+ const auto dist = ranges::end(x.parent_->base_) - *x.parent_->current_;
6788
+ if (dist < x.parent_->remainder_) {
6789
+ return dist == 0 ? 0 : 1;
6790
+ }
6791
+ return div-ceil(dist - x.parent_->remainder_, x.parent_->n_) + 1;
6792
+ ```
6793
+
6794
+ ``` cpp
6795
+ friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)
6796
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6797
+ ```
6798
+
6799
+ *Effects:* Equivalent to: `return -(y - x);`
6800
+
6801
+ #### Class `chunk_view::outer-iterator::value_type` <a id="range.chunk.outer.value">[[range.chunk.outer.value]]</a>
6802
+
6803
+ ``` cpp
6804
+ namespace std::ranges {
6805
+ template<view V>
6806
+ requires input_range<V>
6807
+ struct chunk_view<V>::outer-iterator::value_type : view_interface<value_type> {
6808
+ private:
6809
+ chunk_view* parent_; // exposition only
6810
+
6811
+ constexpr explicit value_type(chunk_view& parent); // exposition only
6812
+
6813
+ public:
6814
+ constexpr inner-iterator begin() const noexcept;
6815
+ constexpr default_sentinel_t end() const noexcept;
6816
+
6817
+ constexpr auto size() const
6818
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6819
+ };
6820
+ }
6821
+ ```
6822
+
6823
+ ``` cpp
6824
+ constexpr explicit value_type(chunk_view& parent);
6825
+ ```
6826
+
6827
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
6828
+
6829
+ ``` cpp
6830
+ constexpr inner-iterator begin() const noexcept;
6831
+ ```
6832
+
6833
+ *Returns:* *`inner-iterator`*`(*`*`parent_`*`)`.
6834
+
6835
+ ``` cpp
6836
+ constexpr default_sentinel_t end() const noexcept;
6837
+ ```
6838
+
6839
+ *Returns:* `default_sentinel`.
6840
+
6841
+ ``` cpp
6842
+ constexpr auto size() const
6843
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6844
+ ```
6845
+
6846
+ *Effects:* Equivalent to:
6847
+
6848
+ ``` cpp
6849
+ return to-unsigned-like(ranges::min(parent_->remainder_,
6850
+ ranges::end(parent_->base_) - *parent_->current_));
6851
+ ```
6852
+
6853
+ #### Class `chunk_view::inner-iterator` <a id="range.chunk.inner.iter">[[range.chunk.inner.iter]]</a>
6854
+
6855
+ ``` cpp
6856
+ namespace std::ranges {
6857
+ template<view V>
6858
+ requires input_range<V>
6859
+ class chunk_view<V>::inner-iterator {
6860
+ chunk_view* parent_; // exposition only
6861
+
6862
+ constexpr explicit inner-iterator(chunk_view& parent) noexcept; // exposition only
6863
+
6864
+ public:
6865
+ using iterator_concept = input_iterator_tag;
6866
+ using difference_type = range_difference_t<V>;
6867
+ using value_type = range_value_t<V>;
6868
+
6869
+ inner-iterator(inner-iterator&&) = default;
6870
+ inner-iterator& operator=(inner-iterator&&) = default;
6871
+
6872
+ constexpr const iterator_t<V>& base() const &;
6873
+
6874
+ constexpr range_reference_t<V> operator*() const;
6875
+ constexpr inner-iterator& operator++();
6876
+ constexpr void operator++(int);
6877
+
6878
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
6879
+
6880
+ friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)
6881
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6882
+ friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)
6883
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6884
+
6885
+ friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i)
6886
+ noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
6887
+
6888
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
6889
+ noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))
6890
+ requires indirectly_swappable<iterator_t<V>>;
6891
+ };
6892
+ }
6893
+ ```
6894
+
6895
+ ``` cpp
6896
+ constexpr explicit inner-iterator(chunk_view& parent) noexcept;
6897
+ ```
6898
+
6899
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
6900
+
6901
+ ``` cpp
6902
+ constexpr const iterator_t<V>& base() const &;
6903
+ ```
6904
+
6905
+ *Effects:* Equivalent to: `return *`*`parent_`*`->`*`current_`*`;`
6906
+
6907
+ ``` cpp
6908
+ constexpr range_reference_t<V> operator*() const;
6909
+ ```
6910
+
6911
+ *Preconditions:* `*this == default_sentinel` is `false`.
6912
+
6913
+ *Effects:* Equivalent to: `return **`*`parent_`*`->`*`current_`*`;`
6914
+
6915
+ ``` cpp
6916
+ constexpr inner-iterator& operator++();
6917
+ ```
6918
+
6919
+ *Preconditions:* `*this == default_sentinel` is `false`.
6920
+
6921
+ *Effects:* Equivalent to:
6922
+
6923
+ ``` cpp
6924
+ ++*parent_->current_;
6925
+ if (*parent_->current_ == ranges::end(parent_->base_))
6926
+ parent_->remainder_ = 0;
6927
+ else
6928
+ --parent_->remainder_;
6929
+ return *this;
6930
+ ```
6931
+
6932
+ ``` cpp
6933
+ constexpr void operator++(int);
6934
+ ```
6935
+
6936
+ *Effects:* Equivalent to `++*this`.
6937
+
6938
+ ``` cpp
6939
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
6940
+ ```
6941
+
6942
+ *Returns:* `x.`*`parent_`*`->`*`remainder_`*` == 0`.
6943
+
6944
+ ``` cpp
6945
+ friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)
6946
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6947
+ ```
6948
+
6949
+ *Effects:* Equivalent to:
6950
+
6951
+ ``` cpp
6952
+ return ranges::min(x.parent_->remainder_,
6953
+ ranges::end(x.parent_->base_) - *x.parent_->current_);
6954
+ ```
6955
+
6956
+ ``` cpp
6957
+ friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)
6958
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
6959
+ ```
6960
+
6961
+ *Effects:* Equivalent to: `return -(y - x);`
6962
+
6963
+ ``` cpp
6964
+ friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i)
6965
+ noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
6966
+ ```
6967
+
6968
+ *Effects:* Equivalent to:
6969
+ `return ranges::iter_move(*i.`*`parent_`*`->`*`current_`*`);`
6970
+
6971
+ ``` cpp
6972
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
6973
+ noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))
6974
+ requires indirectly_swappable<iterator_t<V>>;
6975
+ ```
6976
+
6977
+ *Effects:* Equivalent to:
6978
+ `ranges::iter_swap(*x.`*`parent_`*`->`*`current_`*`, *y.`*`parent_`*`->`*`current_`*`);`
6979
+
6980
+ #### Class template `chunk_view` for forward ranges <a id="range.chunk.view.fwd">[[range.chunk.view.fwd]]</a>
6981
+
6982
+ ``` cpp
6983
+ namespace std::ranges {
6984
+ template<view V>
6985
+ requires forward_range<V>
6986
+ class chunk_view<V> : public view_interface<chunk_view<V>> {
6987
+ V base_; // exposition only
6988
+ range_difference_t<V> n_; // exposition only
6989
+
6990
+ // [range.chunk.fwd.iter], class template chunk_view::iterator
6991
+ template<bool> class iterator; // exposition only
6992
+
6993
+ public:
6994
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
6995
+
6996
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
6997
+ constexpr V base() && { return std::move(base_); }
6998
+
6999
+ constexpr auto begin() requires (!simple-view<V>) {
7000
+ return iterator<false>(this, ranges::begin(base_));
7001
+ }
7002
+
7003
+ constexpr auto begin() const requires forward_range<const V> {
7004
+ return iterator<true>(this, ranges::begin(base_));
7005
+ }
7006
+
7007
+ constexpr auto end() requires (!simple-view<V>) {
7008
+ if constexpr (common_range<V> && sized_range<V>) {
7009
+ auto missing = (n_ - ranges::distance(base_) % n_) % n_;
7010
+ return iterator<false>(this, ranges::end(base_), missing);
7011
+ } else if constexpr (common_range<V> && !bidirectional_range<V>) {
7012
+ return iterator<false>(this, ranges::end(base_));
7013
+ } else {
7014
+ return default_sentinel;
7015
+ }
7016
+ }
7017
+
7018
+ constexpr auto end() const requires forward_range<const V> {
7019
+ if constexpr (common_range<const V> && sized_range<const V>) {
7020
+ auto missing = (n_ - ranges::distance(base_) % n_) % n_;
7021
+ return iterator<true>(this, ranges::end(base_), missing);
7022
+ } else if constexpr (common_range<const V> && !bidirectional_range<const V>) {
7023
+ return iterator<true>(this, ranges::end(base_));
7024
+ } else {
7025
+ return default_sentinel;
7026
+ }
7027
+ }
7028
+
7029
+ constexpr auto size() requires sized_range<V>;
7030
+ constexpr auto size() const requires sized_range<const V>;
7031
+ };
7032
+ }
7033
+ ```
7034
+
7035
+ ``` cpp
7036
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
7037
+ ```
7038
+
7039
+ *Preconditions:* `n > 0` is `true`.
7040
+
7041
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
7042
+ `n`.
7043
+
7044
+ ``` cpp
7045
+ constexpr auto size() requires sized_range<V>;
7046
+ constexpr auto size() const requires sized_range<const V>;
7047
+ ```
7048
+
7049
+ *Effects:* Equivalent to:
7050
+
7051
+ ``` cpp
7052
+ return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
7053
+ ```
7054
+
7055
+ #### Class template `chunk_view::iterator` for forward ranges <a id="range.chunk.fwd.iter">[[range.chunk.fwd.iter]]</a>
7056
+
7057
+ ``` cpp
7058
+ namespace std::ranges {
7059
+ template<view V>
7060
+ requires forward_range<V>
7061
+ template<bool Const>
7062
+ class chunk_view<V>::iterator {
7063
+ using Parent = maybe-const<Const, chunk_view>; // exposition only
7064
+ using Base = maybe-const<Const, V>; // exposition only
7065
+
7066
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
7067
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
7068
+ range_difference_t<Base> n_ = 0; // exposition only
7069
+ range_difference_t<Base> missing_ = 0; // exposition only
7070
+
7071
+ constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only
7072
+ range_difference_t<Base> missing = 0);
7073
+
7074
+ public:
7075
+ using iterator_category = input_iterator_tag;
7076
+ using iterator_concept = see below;
7077
+ using value_type = decltype(views::take(subrange(current_, end_), n_));
7078
+ using difference_type = range_difference_t<Base>;
7079
+
7080
+ iterator() = default;
7081
+ constexpr iterator(iterator<!Const> i)
7082
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
7083
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
7084
+
7085
+ constexpr iterator_t<Base> base() const;
7086
+
7087
+ constexpr value_type operator*() const;
7088
+ constexpr iterator& operator++();
7089
+ constexpr iterator operator++(int);
7090
+
7091
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
7092
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
7093
+
7094
+ constexpr iterator& operator+=(difference_type x)
7095
+ requires random_access_range<Base>;
7096
+ constexpr iterator& operator-=(difference_type x)
7097
+ requires random_access_range<Base>;
7098
+
7099
+ constexpr value_type operator[](difference_type n) const
7100
+ requires random_access_range<Base>;
7101
+
7102
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
7103
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
7104
+
7105
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
7106
+ requires random_access_range<Base>;
7107
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
7108
+ requires random_access_range<Base>;
7109
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
7110
+ requires random_access_range<Base>;
7111
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
7112
+ requires random_access_range<Base>;
7113
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
7114
+ requires random_access_range<Base> &&
7115
+ three_way_comparable<iterator_t<Base>>;
7116
+
7117
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
7118
+ requires random_access_range<Base>;
7119
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
7120
+ requires random_access_range<Base>;
7121
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
7122
+ requires random_access_range<Base>;
7123
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7124
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
7125
+
7126
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
7127
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
7128
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
7129
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
7130
+ };
7131
+ }
7132
+ ```
7133
+
7134
+ `iterator::iterator_concept` is defined as follows:
7135
+
7136
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
7137
+ denotes `random_access_iterator_tag`.
7138
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
7139
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
7140
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
7141
+
7142
+ ``` cpp
7143
+ constexpr iterator(Parent* parent, iterator_t<Base> current,
7144
+ range_difference_t<Base> missing = 0);
7145
+ ```
7146
+
7147
+ *Effects:* Initializes *current\_* with `current`, *end\_* with
7148
+ `ranges::end(parent->`*`base_`*`)`, *n\_* with `parent->`*`n_`*, and
7149
+ *missing\_* with `missing`.
7150
+
7151
+ ``` cpp
7152
+ constexpr iterator(iterator<!Const> i)
7153
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
7154
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
7155
+ ```
7156
+
7157
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`,
7158
+ *end\_* with `std::move(i.`*`end_`*`)`, *n\_* with `i.`*`n_`*, and
7159
+ *missing\_* with `i.`*`missing_`*.
7160
+
7161
+ ``` cpp
7162
+ constexpr iterator_t<Base> base() const;
7163
+ ```
7164
+
7165
+ *Returns:* *current\_*.
7166
+
7167
+ ``` cpp
7168
+ constexpr value_type operator*() const;
7169
+ ```
7170
+
7171
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
7172
+
7173
+ *Returns:*
7174
+ `views::take(subrange(`*`current_`*`, `*`end_`*`), `*`n_`*`)`.
7175
+
7176
+ ``` cpp
7177
+ constexpr iterator& operator++();
7178
+ ```
7179
+
7180
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
7181
+
7182
+ *Effects:* Equivalent to:
7183
+
7184
+ ``` cpp
7185
+ missing_ = ranges::advance(current_, n_, end_);
7186
+ return *this;
7187
+ ```
7188
+
7189
+ ``` cpp
7190
+ constexpr iterator operator++(int);
7191
+ ```
7192
+
7193
+ *Effects:* Equivalent to:
7194
+
7195
+ ``` cpp
7196
+ auto tmp = *this;
7197
+ ++*this;
7198
+ return tmp;
7199
+ ```
7200
+
7201
+ ``` cpp
7202
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
7203
+ ```
7204
+
7205
+ *Effects:* Equivalent to:
7206
+
7207
+ ``` cpp
7208
+ ranges::advance(current_, missing_ - n_);
7209
+ missing_ = 0;
7210
+ return *this;
7211
+ ```
7212
+
7213
+ ``` cpp
7214
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
7215
+ ```
7216
+
7217
+ *Effects:* Equivalent to:
7218
+
7219
+ ``` cpp
7220
+ auto tmp = *this;
7221
+ --*this;
7222
+ return tmp;
7223
+ ```
7224
+
7225
+ ``` cpp
7226
+ constexpr iterator& operator+=(difference_type x)
7227
+ requires random_access_range<Base>;
7228
+ ```
7229
+
7230
+ *Preconditions:* If `x` is positive,
7231
+ `ranges::distance(`*`current_`*`, `*`end_`*`) > `*`n_`*` * (x - 1)` is
7232
+ `true`.
7233
+
7234
+ [*Note 1*: If `x` is negative, the *Effects* paragraph implies a
7235
+ precondition. — *end note*]
7236
+
7237
+ *Effects:* Equivalent to:
7238
+
7239
+ ``` cpp
7240
+ if (x > 0) {
7241
+ ranges::advance(current_, n_ * (x - 1));
7242
+ missing_ = ranges::advance(current_, n_, end_);
7243
+ } else if (x < 0) {
7244
+ ranges::advance(current_, n_ * x + missing_);
7245
+ missing_ = 0;
7246
+ }
7247
+ return *this;
7248
+ ```
7249
+
7250
+ ``` cpp
7251
+ constexpr iterator& operator-=(difference_type x)
7252
+ requires random_access_range<Base>;
7253
+ ```
7254
+
7255
+ *Effects:* Equivalent to: `return *this += -x;`
7256
+
7257
+ ``` cpp
7258
+ constexpr value_type operator[](difference_type n) const
7259
+ requires random_access_range<Base>;
7260
+ ```
7261
+
7262
+ *Returns:* `*(*this + n)`.
7263
+
7264
+ ``` cpp
7265
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
7266
+ ```
7267
+
7268
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
7269
+
7270
+ ``` cpp
7271
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
7272
+ ```
7273
+
7274
+ *Returns:* `x.`*`current_`*` == x.`*`end_`*.
7275
+
7276
+ ``` cpp
7277
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
7278
+ requires random_access_range<Base>;
7279
+ ```
7280
+
7281
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
7282
+
7283
+ ``` cpp
7284
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
7285
+ requires random_access_range<Base>;
7286
+ ```
7287
+
7288
+ *Effects:* Equivalent to: `return y < x;`
7289
+
7290
+ ``` cpp
7291
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
7292
+ requires random_access_range<Base>;
7293
+ ```
7294
+
7295
+ *Effects:* Equivalent to: `return !(y < x);`
7296
+
7297
+ ``` cpp
7298
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
7299
+ requires random_access_range<Base>;
7300
+ ```
7301
+
7302
+ *Effects:* Equivalent to: `return !(x < y);`
7303
+
7304
+ ``` cpp
7305
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
7306
+ requires random_access_range<Base> &&
7307
+ three_way_comparable<iterator_t<Base>>;
7308
+ ```
7309
+
7310
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
7311
+
7312
+ ``` cpp
7313
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
7314
+ requires random_access_range<Base>;
7315
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
7316
+ requires random_access_range<Base>;
7317
+ ```
7318
+
7319
+ *Effects:* Equivalent to:
7320
+
7321
+ ``` cpp
7322
+ auto r = i;
7323
+ r += n;
7324
+ return r;
7325
+ ```
7326
+
7327
+ ``` cpp
7328
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
7329
+ requires random_access_range<Base>;
7330
+ ```
7331
+
7332
+ *Effects:* Equivalent to:
7333
+
7334
+ ``` cpp
7335
+ auto r = i;
7336
+ r -= n;
7337
+ return r;
7338
+ ```
7339
+
7340
+ ``` cpp
7341
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7342
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
7343
+ ```
7344
+
7345
+ *Returns:*
7346
+ `(x.`*`current_`*` - y.`*`current_`*` + x.`*`missing_`*` - y.`*`missing_`*`) / x.`*`n_`*.
7347
+
7348
+ ``` cpp
7349
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
7350
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
7351
+ ```
7352
+
7353
+ *Returns:* *`div-ceil`*`(x.`*`end_`*` - x.`*`current_`*`, x.`*`n_`*`)`.
7354
+
7355
+ ``` cpp
7356
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
7357
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
7358
+ ```
7359
+
7360
+ *Effects:* Equivalent to: `return -(y - x);`
7361
+
7362
+ ### Slide view <a id="range.slide">[[range.slide]]</a>
7363
+
7364
+ #### Overview <a id="range.slide.overview">[[range.slide.overview]]</a>
7365
+
7366
+ `slide_view` takes a view and a number N and produces a view whose Mᵗʰ
7367
+ element is a view over the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
7368
+ original view. If the original view has fewer than N elements, the
7369
+ resulting view is empty.
7370
+
7371
+ The name `views::slide` denotes a range adaptor object
7372
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
7373
+ expression `views::slide(E, N)` is expression-equivalent to
7374
+ `slide_view(E, N)`.
7375
+
7376
+ [*Example 1*:
7377
+
7378
+ ``` cpp
7379
+ vector v = {1, 2, 3, 4};
7380
+
7381
+ for (auto i : v | views::slide(2)) {
7382
+ cout << '[' << i[0] << ", " << i[1] << "] "; // prints [1, 2] [2, 3] [3, 4]
7383
+ }
7384
+ ```
7385
+
7386
+ — *end example*]
7387
+
7388
+ #### Class template `slide_view` <a id="range.slide.view">[[range.slide.view]]</a>
7389
+
7390
+ ``` cpp
7391
+ namespace std::ranges {
7392
+ template<class V>
7393
+ concept slide-caches-nothing = random_access_range<V> && sized_range<V>; // exposition only
7394
+
7395
+ template<class V>
7396
+ concept slide-caches-last = // exposition only
7397
+ !slide-caches-nothing<V> && bidirectional_range<V> && common_range<V>;
7398
+
7399
+ template<class V>
7400
+ concept slide-caches-first = // exposition only
7401
+ !slide-caches-nothing<V> && !slide-caches-last<V>;
7402
+
7403
+ template<forward_range V>
7404
+ requires view<V>
7405
+ class slide_view : public view_interface<slide_view<V>> {
7406
+ V base_; // exposition only
7407
+ range_difference_t<V> n_; // exposition only
7408
+
7409
+ // [range.slide.iterator], class template slide_view::iterator
7410
+ template<bool> class iterator; // exposition only
7411
+
7412
+ // [range.slide.sentinel], class slide_view::sentinel
7413
+ class sentinel; // exposition only
7414
+
7415
+ public:
7416
+ constexpr explicit slide_view(V base, range_difference_t<V> n);
7417
+
7418
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
7419
+ constexpr V base() && { return std::move(base_); }
7420
+
7421
+ constexpr auto begin()
7422
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
7423
+ constexpr auto begin() const requires slide-caches-nothing<const V>;
7424
+
7425
+ constexpr auto end()
7426
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
7427
+ constexpr auto end() const requires slide-caches-nothing<const V>;
7428
+
7429
+ constexpr auto size() requires sized_range<V>;
7430
+ constexpr auto size() const requires sized_range<const V>;
7431
+ };
7432
+
7433
+ template<class R>
7434
+ slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>;
7435
+ }
7436
+ ```
7437
+
7438
+ ``` cpp
7439
+ constexpr explicit slide_view(V base, range_difference_t<V> n);
7440
+ ```
7441
+
7442
+ *Preconditions:* `n > 0` is `true`.
7443
+
7444
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
7445
+ `n`.
7446
+
7447
+ ``` cpp
7448
+ constexpr auto begin()
7449
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
7450
+ ```
7451
+
7452
+ *Returns:*
7453
+
7454
+ - If `V` models `slide-caches-first`,
7455
+ ``` cpp
7456
+ iterator<false>(ranges::begin(base_),
7457
+ ranges::next(ranges::begin(base_), n_ - 1, ranges::end(base_)), n_)
7458
+ ```
7459
+ - Otherwise,
7460
+ *`iterator`*`<false>(ranges::begin(`*`base_`*`), `*`n_`*`)`.
7461
+
7462
+ *Remarks:* In order to provide the amortized constant-time complexity
7463
+ required by the `range` concept, this function caches the result within
7464
+ the `slide_view` for use on subsequent calls when `V` models
7465
+ `slide-caches-first`.
7466
+
7467
+ ``` cpp
7468
+ constexpr auto begin() const requires slide-caches-nothing<const V>;
7469
+ ```
7470
+
7471
+ *Returns:* *`iterator`*`<true>(ranges::begin(`*`base_`*`), `*`n_`*`)`.
7472
+
7473
+ ``` cpp
7474
+ constexpr auto end()
7475
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
7476
+ ```
7477
+
7478
+ *Returns:*
7479
+
7480
+ - If `V` models `slide-caches-nothing`,
7481
+ ``` cpp
7482
+ iterator<false>(ranges::begin(base_) + range_difference_t<V>(size()), n_)
7483
+ ```
7484
+ - Otherwise, if `V` models `slide-caches-last`,
7485
+ ``` cpp
7486
+ iterator<false>(ranges::prev(ranges::end(base_), n_ - 1, ranges::begin(base_)), n_)
7487
+ ```
7488
+ - Otherwise, if `V` models `common_range`,
7489
+ ``` cpp
7490
+ iterator<false>(ranges::end(base_), ranges::end(base_), n_)
7491
+ ```
7492
+ - Otherwise, *`sentinel`*`(ranges::end(`*`base_`*`))`.
7493
+
7494
+ *Remarks:* In order to provide the amortized constant-time complexity
7495
+ required by the `range` concept, this function caches the result within
7496
+ the `slide_view` for use on subsequent calls when `V` models
7497
+ `slide-caches-last`.
7498
+
7499
+ ``` cpp
7500
+ constexpr auto end() const requires slide-caches-nothing<const V>;
7501
+ ```
7502
+
7503
+ *Returns:* `begin() + range_difference_t<const V>(size())`.
7504
+
7505
+ ``` cpp
7506
+ constexpr auto size() requires sized_range<V>;
7507
+ constexpr auto size() const requires sized_range<const V>;
7508
+ ```
7509
+
7510
+ *Effects:* Equivalent to:
7511
+
7512
+ ``` cpp
7513
+ auto sz = ranges::distance(base_) - n_ + 1;
7514
+ if (sz < 0) sz = 0;
7515
+ return to-unsigned-like(sz);
7516
+ ```
7517
+
7518
+ #### Class template `slide_view::iterator` <a id="range.slide.iterator">[[range.slide.iterator]]</a>
7519
+
7520
+ ``` cpp
7521
+ namespace std::ranges {
7522
+ template<forward_range V>
7523
+ requires view<V>
7524
+ template<bool Const>
7525
+ class slide_view<V>::iterator {
7526
+ using Base = maybe-const<Const, V>; // exposition only
7527
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
7528
+ iterator_t<Base> last_ele_ = iterator_t<Base>(); // exposition only,
7529
+ // present only if Base models slide-caches-first
7530
+ range_difference_t<Base> n_ = 0; // exposition only
7531
+
7532
+ constexpr iterator(iterator_t<Base> current, range_difference_t<Base> n) // exposition only
7533
+ requires (!slide-caches-first<Base>);
7534
+
7535
+ constexpr iterator(iterator_t<Base> current, iterator_t<Base> last_ele, // exposition only
7536
+ range_difference_t<Base> n)
7537
+ requires slide-caches-first<Base>;
7538
+
7539
+ public:
7540
+ using iterator_category = input_iterator_tag;
7541
+ using iterator_concept = see below;
7542
+ using value_type = decltype(views::counted(current_, n_));
7543
+ using difference_type = range_difference_t<Base>;
7544
+
7545
+ iterator() = default;
7546
+ constexpr iterator(iterator<!Const> i)
7547
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
7548
+
7549
+ constexpr auto operator*() const;
7550
+ constexpr iterator& operator++();
7551
+ constexpr iterator operator++(int);
7552
+
7553
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
7554
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
7555
+
7556
+ constexpr iterator& operator+=(difference_type x)
7557
+ requires random_access_range<Base>;
7558
+ constexpr iterator& operator-=(difference_type x)
7559
+ requires random_access_range<Base>;
7560
+
7561
+ constexpr auto operator[](difference_type n) const
7562
+ requires random_access_range<Base>;
7563
+
7564
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
7565
+
7566
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
7567
+ requires random_access_range<Base>;
7568
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
7569
+ requires random_access_range<Base>;
7570
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
7571
+ requires random_access_range<Base>;
7572
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
7573
+ requires random_access_range<Base>;
7574
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
7575
+ requires random_access_range<Base> &&
7576
+ three_way_comparable<iterator_t<Base>>;
7577
+
7578
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
7579
+ requires random_access_range<Base>;
7580
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
7581
+ requires random_access_range<Base>;
7582
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
7583
+ requires random_access_range<Base>;
7584
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7585
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
7586
+ };
7587
+ }
7588
+ ```
7589
+
7590
+ `iterator::iterator_concept` is defined as follows:
7591
+
7592
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
7593
+ denotes `random_access_iterator_tag`.
7594
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
7595
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
7596
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
7597
+
7598
+ If the invocation of any non-const member function of *`iterator`* exits
7599
+ via an exception, the *`iterator`* acquires a singular value.
7600
+
7601
+ ``` cpp
7602
+ constexpr iterator(iterator_t<Base> current, range_difference_t<Base> n)
7603
+ requires (!slide-caches-first<Base>);
7604
+ ```
7605
+
7606
+ *Effects:* Initializes *current\_* with `current` and *n\_* with `n`.
7607
+
7608
+ ``` cpp
7609
+ constexpr iterator(iterator_t<Base> current, iterator_t<Base> last_ele,
7610
+ range_difference_t<Base> n)
7611
+ requires slide-caches-first<Base>;
7612
+ ```
7613
+
7614
+ *Effects:* Initializes *current\_* with `current`, *last_ele\_* with
7615
+ `last_ele`, and *n\_* with `n`.
7616
+
7617
+ ``` cpp
7618
+ constexpr iterator(iterator<!Const> i)
7619
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
7620
+ ```
7621
+
7622
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
7623
+ and *n\_* with `i.`*`n_`*.
7624
+
7625
+ [*Note 1*: *`iterator`*`<true>` can only be formed when *Base* models
7626
+ `slide-caches-nothing`, in which case *last_ele\_* is not
7627
+ present. — *end note*]
7628
+
7629
+ ``` cpp
7630
+ constexpr auto operator*() const;
7631
+ ```
7632
+
7633
+ *Returns:* `views::counted(`*`current_`*`, `*`n_`*`)`.
7634
+
7635
+ ``` cpp
7636
+ constexpr iterator& operator++();
7637
+ ```
7638
+
7639
+ *Preconditions:* *current\_* and *last_ele\_* (if present) are
7640
+ incrementable.
7641
+
7642
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
7643
+ `ranges::next(i)`, where `i` is the value of that data member before the
7644
+ call.
7645
+
7646
+ *Returns:* `*this`.
7647
+
7648
+ ``` cpp
7649
+ constexpr iterator operator++(int);
7650
+ ```
7651
+
7652
+ *Effects:* Equivalent to:
7653
+
7654
+ ``` cpp
7655
+ auto tmp = *this;
7656
+ ++*this;
7657
+ return tmp;
7658
+ ```
7659
+
7660
+ ``` cpp
7661
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
7662
+ ```
7663
+
7664
+ *Preconditions:* *current\_* and *last_ele\_* (if present) are
7665
+ decrementable.
7666
+
7667
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
7668
+ `ranges::prev(i)`, where `i` is the value of that data member before the
7669
+ call.
7670
+
7671
+ *Returns:* `*this`.
7672
+
7673
+ ``` cpp
7674
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
7675
+ ```
7676
+
7677
+ *Effects:* Equivalent to:
7678
+
7679
+ ``` cpp
7680
+ auto tmp = *this;
7681
+ --*this;
7682
+ return tmp;
7683
+ ```
7684
+
7685
+ ``` cpp
7686
+ constexpr iterator& operator+=(difference_type x)
7687
+ requires random_access_range<Base>;
7688
+ ```
7689
+
7690
+ *Preconditions:* *`current_`*` + x` and *`last_ele_`*` + x` (if
7691
+ *last_ele\_* is present) have well-defined behavior.
7692
+
7693
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
7694
+ `i + x`, where `i` is the value of that data member before the call.
7695
+
7696
+ *Returns:* `*this`.
7697
+
7698
+ ``` cpp
7699
+ constexpr iterator& operator-=(difference_type x)
7700
+ requires random_access_range<Base>;
7701
+ ```
7702
+
7703
+ *Preconditions:* *`current_`*` - x` and *`last_ele_`*` - x` (if
7704
+ *last_ele\_* is present) have well-defined behavior.
7705
+
7706
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
7707
+ `i - x`, where `i` is the value of that data member before the call.
7708
+
7709
+ *Returns:* `*this`.
7710
+
7711
+ ``` cpp
7712
+ constexpr auto operator[](difference_type n) const
7713
+ requires random_access_range<Base>;
7714
+ ```
7715
+
7716
+ *Effects:* Equivalent to:
7717
+ `return views::counted(`*`current_`*` + n, `*`n_`*`);`
7718
+
7719
+ ``` cpp
7720
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
7721
+ ```
7722
+
7723
+ *Returns:* If *last_ele\_* is present,
7724
+ `x.`*`last_ele_`*` == y.`*`last_ele_`*; otherwise,
7725
+ `x.`*`current_`*` == y.`*`current_`*.
7726
+
7727
+ ``` cpp
7728
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
7729
+ requires random_access_range<Base>;
7730
+ ```
7731
+
7732
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
7733
+
7734
+ ``` cpp
7735
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
7736
+ requires random_access_range<Base>;
7737
+ ```
7738
+
7739
+ *Effects:* Equivalent to: `return y < x;`
7740
+
7741
+ ``` cpp
7742
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
7743
+ requires random_access_range<Base>;
7744
+ ```
7745
+
7746
+ *Effects:* Equivalent to: `return !(y < x);`
7747
+
7748
+ ``` cpp
7749
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
7750
+ requires random_access_range<Base>;
7751
+ ```
7752
+
7753
+ *Effects:* Equivalent to: `return !(x < y);`
7754
+
7755
+ ``` cpp
7756
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
7757
+ requires random_access_range<Base> &&
7758
+ three_way_comparable<iterator_t<Base>>;
7759
+ ```
7760
+
7761
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
7762
+
7763
+ ``` cpp
7764
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
7765
+ requires random_access_range<Base>;
7766
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
7767
+ requires random_access_range<Base>;
7768
+ ```
7769
+
7770
+ *Effects:* Equivalent to:
7771
+
7772
+ ``` cpp
7773
+ auto r = i;
7774
+ r += n;
7775
+ return r;
7776
+ ```
7777
+
7778
+ ``` cpp
7779
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
7780
+ requires random_access_range<Base>;
7781
+ ```
7782
+
7783
+ *Effects:* Equivalent to:
7784
+
7785
+ ``` cpp
7786
+ auto r = i;
7787
+ r -= n;
7788
+ return r;
7789
+ ```
7790
+
7791
+ ``` cpp
7792
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7793
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
7794
+ ```
7795
+
7796
+ *Returns:* If *last_ele\_* is present,
7797
+ `x.`*`last_ele_`*` - y.`*`last_ele_`*; otherwise,
7798
+ `x.`*`current_`*` - y.`*`current_`*.
7799
+
7800
+ #### Class `slide_view::sentinel` <a id="range.slide.sentinel">[[range.slide.sentinel]]</a>
7801
+
7802
+ ``` cpp
7803
+ namespace std::ranges {
7804
+ template<forward_range V>
7805
+ requires view<V>
7806
+ class slide_view<V>::sentinel {
7807
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
7808
+ constexpr explicit sentinel(sentinel_t<V> end); // exposition only
7809
+
7810
+ public:
7811
+ sentinel() = default;
7812
+
7813
+ friend constexpr bool operator==(const iterator<false>& x, const sentinel& y);
7814
+
7815
+ friend constexpr range_difference_t<V>
7816
+ operator-(const iterator<false>& x, const sentinel& y)
7817
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
7818
+
7819
+ friend constexpr range_difference_t<V>
7820
+ operator-(const sentinel& y, const iterator<false>& x)
7821
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
7822
+ };
7823
+ }
7824
+ ```
7825
+
7826
+ [*Note 1*: *`sentinel`* is used only when `slide-caches-first<V>` is
7827
+ `true`. — *end note*]
7828
+
7829
+ ``` cpp
7830
+ constexpr explicit sentinel(sentinel_t<V> end);
7831
+ ```
7832
+
7833
+ *Effects:* Initializes *end\_* with `end`.
7834
+
7835
+ ``` cpp
7836
+ friend constexpr bool operator==(const iterator<false>& x, const sentinel& y);
7837
+ ```
7838
+
7839
+ *Returns:* `x.`*`last_ele_`*` == y.`*`end_`*.
7840
+
7841
+ ``` cpp
7842
+ friend constexpr range_difference_t<V>
7843
+ operator-(const iterator<false>& x, const sentinel& y)
7844
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
7845
+ ```
7846
+
7847
+ *Returns:* `x.`*`last_ele_`*` - y.`*`end_`*.
7848
+
7849
+ ``` cpp
7850
+ friend constexpr range_difference_t<V>
7851
+ operator-(const sentinel& y, const iterator<false>& x)
7852
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
7853
+ ```
7854
+
7855
+ *Returns:* `y.`*`end_`*` - x.`*`last_ele_`*.
7856
+
7857
+ ### Chunk by view <a id="range.chunk.by">[[range.chunk.by]]</a>
7858
+
7859
+ #### Overview <a id="range.chunk.by.overview">[[range.chunk.by.overview]]</a>
7860
+
7861
+ `chunk_by_view` takes a view and a predicate, and splits the view into
7862
+ `subrange`s between each pair of adjacent elements for which the
7863
+ predicate returns `false`.
7864
+
7865
+ The name `views::chunk_by` denotes a range adaptor object
7866
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
7867
+ expression `views::chunk_by(E, F)` is expression-equivalent to
7868
+ `chunk_by_view(E, F)`.
7869
+
7870
+ [*Example 1*:
7871
+
7872
+ ``` cpp
7873
+ vector v = {1, 2, 2, 3, 0, 4, 5, 2};
7874
+
7875
+ for (auto r : v | views::chunk_by(ranges::less_equal{})) {
7876
+ cout << '[';
7877
+ auto sep = "";
7878
+ for (auto i : r) {
7879
+ cout << sep << i;
7880
+ sep = ", ";
7881
+ }
7882
+ cout << "] ";
7883
+ }
7884
+ // The above prints [1, 2, 2, 3] [0, 4, 5] [2]
7885
+ ```
7886
+
7887
+ — *end example*]
7888
+
7889
+ #### Class template `chunk_by_view` <a id="range.chunk.by.view">[[range.chunk.by.view]]</a>
7890
+
7891
+ ``` cpp
7892
+ namespace std::ranges {
7893
+ template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred>
7894
+ requires view<V> && is_object_v<Pred>
7895
+ class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> {
7896
+ V base_ = V(); // exposition only
7897
+ movable-box<Pred> pred_; // exposition only
7898
+
7899
+ // [range.chunk.by.iter], class chunk_by_view::iterator
7900
+ class iterator; // exposition only
7901
+
7902
+ public:
7903
+ chunk_by_view() requires default_initializable<V> && default_initializable<Pred> = default;
7904
+ constexpr explicit chunk_by_view(V base, Pred pred);
7905
+
7906
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
7907
+ constexpr V base() && { return std::move(base_); }
7908
+
7909
+ constexpr const Pred& pred() const;
7910
+
7911
+ constexpr iterator begin();
7912
+ constexpr auto end();
7913
+
7914
+ constexpr iterator_t<V> find-next(iterator_t<V>); // exposition only
7915
+ constexpr iterator_t<V> find-prev(iterator_t<V>) // exposition only
7916
+ requires bidirectional_range<V>;
7917
+ };
7918
+
7919
+ template<class R, class Pred>
7920
+ chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, Pred>;
7921
+ }
7922
+ ```
7923
+
7924
+ ``` cpp
7925
+ constexpr explicit chunk_by_view(V base, Pred pred);
7926
+ ```
7927
+
7928
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
7929
+ `std::move(pred)`.
7930
+
7931
+ ``` cpp
7932
+ constexpr const Pred& pred() const;
7933
+ ```
7934
+
7935
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
7936
+
7937
+ ``` cpp
7938
+ constexpr iterator begin();
7939
+ ```
7940
+
7941
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
7942
+
7943
+ *Returns:*
7944
+ *`iterator`*`(*this, ranges::begin(`*`base_`*`), `*`find-next`*`(ranges::begin(`*`base_`*`)))`.
7945
+
7946
+ *Remarks:* In order to provide the amortized constant-time complexity
7947
+ required by the `range` concept, this function caches the result within
7948
+ the `chunk_by_view` for use on subsequent calls.
7949
+
7950
+ ``` cpp
7951
+ constexpr auto end();
7952
+ ```
7953
+
7954
+ *Effects:* Equivalent to:
7955
+
7956
+ ``` cpp
7957
+ if constexpr (common_range<V>) {
7958
+ return iterator(*this, ranges::end(base_), ranges::end(base_));
7959
+ } else {
7960
+ return default_sentinel;
7961
+ }
7962
+ ```
7963
+
7964
+ ``` cpp
7965
+ constexpr iterator_t<V> find-next(iterator_t<V> current);
7966
+ ```
7967
+
7968
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
7969
+
7970
+ *Returns:*
7971
+
7972
+ ``` cpp
7973
+ ranges::next(ranges::adjacent_find(current, ranges::end(base_), not_fn(ref(*pred_))),
7974
+ 1, ranges::end(base_))
7975
+ ```
7976
+
7977
+ ``` cpp
7978
+ constexpr iterator_t<V> find-prev(iterator_t<V> current) requires bidirectional_range<V>;
7979
+ ```
7980
+
7981
+ *Preconditions:*
7982
+
7983
+ - `current` is not equal to `ranges::begin(`*`base_`*`)`.
7984
+ - *`pred_`*`.has_value()` is `true`.
7985
+
7986
+ *Returns:* An iterator `i` in the range \[`ranges::begin(`*`base_`*`)`,
7987
+ `current`) such that:
7988
+
7989
+ - `ranges::adjacent_find(i, current, not_fn(ref(*`*`pred_`*`)))` is
7990
+ equal to `current`; and
7991
+ - if `i` is not equal to `ranges::begin(`*`base_`*`)`, then
7992
+ `bool(invoke(*`*`pred_`*`, *ranges::prev(i), *i))` is `false`.
7993
+
7994
+ #### Class `chunk_by_view::iterator` <a id="range.chunk.by.iter">[[range.chunk.by.iter]]</a>
7995
+
7996
+ ``` cpp
7997
+ namespace std::ranges {
7998
+ template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred>
7999
+ requires view<V> && is_object_v<Pred>
8000
+ class chunk_by_view<V, Pred>::iterator {
8001
+ chunk_by_view* parent_ = nullptr; // exposition only
8002
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only
8003
+ iterator_t<V> next_ = iterator_t<V>(); // exposition only
8004
+
8005
+ constexpr iterator(chunk_by_view& parent, iterator_t<V> current, // exposition only
8006
+ iterator_t<V> next);
8007
+
8008
+ public:
8009
+ using value_type = subrange<iterator_t<V>>;
8010
+ using difference_type = range_difference_t<V>;
8011
+ using iterator_category = input_iterator_tag;
8012
+ using iterator_concept = see below;
8013
+
8014
+ iterator() = default;
8015
+
8016
+ constexpr value_type operator*() const;
8017
+ constexpr iterator& operator++();
8018
+ constexpr iterator operator++(int);
8019
+
8020
+ constexpr iterator& operator--() requires bidirectional_range<V>;
8021
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
8022
+
8023
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
8024
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
8025
+ };
8026
+ }
8027
+ ```
8028
+
8029
+ `iterator::iterator_concept` is defined as follows:
8030
+
8031
+ - If `V` models `bidirectional_range`, then `iterator_concept` denotes
8032
+ `bidirectional_iterator_tag`.
8033
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
8034
+
8035
+ ``` cpp
8036
+ constexpr iterator(chunk_by_view& parent, iterator_t<V> current, iterator_t<V> next);
8037
+ ```
8038
+
8039
+ *Effects:* Initializes *parent\_* with `addressof(parent)`, *current\_*
8040
+ with `current`, and *next\_* with `next`.
8041
+
8042
+ ``` cpp
8043
+ constexpr value_type operator*() const;
8044
+ ```
8045
+
8046
+ *Preconditions:* *current\_* is not equal to *next\_*.
8047
+
8048
+ *Returns:* `subrange(`*`current_`*`, `*`next_`*`)`.
8049
+
8050
+ ``` cpp
8051
+ constexpr iterator& operator++();
8052
+ ```
8053
+
8054
+ *Preconditions:* *current\_* is not equal to *next\_*.
8055
+
8056
+ *Effects:* Equivalent to:
8057
+
8058
+ ``` cpp
8059
+ current_ = next_;
8060
+ next_ = parent_->find-next(current_);
8061
+ return *this;
8062
+ ```
8063
+
8064
+ ``` cpp
8065
+ constexpr iterator operator++(int);
8066
+ ```
8067
+
8068
+ *Effects:* Equivalent to:
8069
+
8070
+ ``` cpp
8071
+ auto tmp = *this;
8072
+ ++*this;
8073
+ return tmp;
8074
+ ```
8075
+
8076
+ ``` cpp
8077
+ constexpr iterator& operator--() requires bidirectional_range<V>;
8078
+ ```
8079
+
8080
+ *Effects:* Equivalent to:
8081
+
8082
+ ``` cpp
8083
+ next_ = current_;
8084
+ current_ = parent_->find-prev(next_);
8085
+ return *this;
8086
+ ```
8087
+
8088
+ ``` cpp
8089
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
8090
+ ```
8091
+
8092
+ *Effects:* Equivalent to:
8093
+
8094
+ ``` cpp
8095
+ auto tmp = *this;
8096
+ --*this;
8097
+ return tmp;
8098
+ ```
8099
+
8100
+ ``` cpp
8101
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
8102
+ ```
8103
+
8104
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
8105
+
8106
+ ``` cpp
8107
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
8108
+ ```
8109
+
8110
+ *Returns:* `x.`*`current_`*` == x.`*`next_`*.
8111
+
8112
+ ### Stride view <a id="range.stride">[[range.stride]]</a>
8113
+
8114
+ #### Overview <a id="range.stride.overview">[[range.stride.overview]]</a>
8115
+
8116
+ `stride_view` presents a view of an underlying sequence, advancing over
8117
+ n elements at a time, as opposed to the usual single-step succession.
8118
+
8119
+ The name `views::stride` denotes a range adaptor object
8120
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
8121
+ expression `views::stride(E, N)` is expression-equivalent to
8122
+ `stride_view(E, N)`.
8123
+
8124
+ [*Example 1*:
8125
+
8126
+ ``` cpp
8127
+ auto input = views::iota(0, 12) | views::stride(3);
8128
+ ranges::copy(input, ostream_iterator<int>(cout, " ")); // prints 0 3 6 9
8129
+ ranges::copy(input | views::reverse, ostream_iterator<int>(cout, " ")); // prints 9 6 3 0
8130
+ ```
8131
+
8132
+ — *end example*]
8133
+
8134
+ #### Class template `stride_view` <a id="range.stride.view">[[range.stride.view]]</a>
8135
+
8136
+ ``` cpp
8137
+ namespace std::ranges {
8138
+ template<input_range V>
8139
+ requires view<V>
8140
+ class stride_view : public view_interface<stride_view<V>> {
8141
+ V base_; // exposition only
8142
+ range_difference_t<V> stride_; // exposition only
8143
+ // [range.stride.iterator], class template stride_view::iterator
8144
+ template<bool> class iterator; // exposition only
8145
+ public:
8146
+ constexpr explicit stride_view(V base, range_difference_t<V> stride);
8147
+
8148
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
8149
+ constexpr V base() && { return std::move(base_); }
8150
+
8151
+ constexpr range_difference_t<V> stride() const noexcept;
8152
+
8153
+ constexpr auto begin() requires (!simple-view<V>) {
8154
+ return iterator<false>(this, ranges::begin(base_));
8155
+ }
8156
+
8157
+ constexpr auto begin() const requires range<const V> {
8158
+ return iterator<true>(this, ranges::begin(base_));
8159
+ }
8160
+
8161
+ constexpr auto end() requires (!simple-view<V>) {
8162
+ if constexpr (common_range<V> && sized_range<V> && forward_range<V>) {
8163
+ auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_;
8164
+ return iterator<false>(this, ranges::end(base_), missing);
8165
+ } else if constexpr (common_range<V> && !bidirectional_range<V>) {
8166
+ return iterator<false>(this, ranges::end(base_));
8167
+ } else {
8168
+ return default_sentinel;
8169
+ }
8170
+ }
8171
+
8172
+ constexpr auto end() const requires range<const V> {
8173
+ if constexpr (common_range<const V> && sized_range<const V> && forward_range<const V>) {
8174
+ auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_;
8175
+ return iterator<true>(this, ranges::end(base_), missing);
8176
+ } else if constexpr (common_range<const V> && !bidirectional_range<const V>) {
8177
+ return iterator<true>(this, ranges::end(base_));
8178
+ } else {
8179
+ return default_sentinel;
8180
+ }
8181
+ }
8182
+
8183
+ constexpr auto size() requires sized_range<V>;
8184
+ constexpr auto size() const requires sized_range<const V>;
8185
+ };
8186
+
8187
+ template<class R>
8188
+ stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;
8189
+ }
8190
+ ```
8191
+
8192
+ ``` cpp
8193
+ constexpr stride_view(V base, range_difference_t<V> stride);
8194
+ ```
8195
+
8196
+ *Preconditions:* `stride > 0` is `true`.
8197
+
8198
+ *Effects:* Initializes *base\_* with `std::move(base)` and *stride\_*
8199
+ with `stride`.
8200
+
8201
+ ``` cpp
8202
+ constexpr range_difference_t<V> stride() const noexcept;
8203
+ ```
8204
+
8205
+ *Returns:* *stride\_*.
8206
+
8207
+ ``` cpp
8208
+ constexpr auto size() requires sized_range<V>;
8209
+ constexpr auto size() const requires sized_range<const V>;
8210
+ ```
8211
+
8212
+ *Effects:* Equivalent to:
8213
+
8214
+ ``` cpp
8215
+ return to-unsigned-like(div-ceil(ranges::distance(base_), stride_));
8216
+ ```
8217
+
8218
+ #### Class template `stride_view::iterator` <a id="range.stride.iterator">[[range.stride.iterator]]</a>
8219
+
8220
+ ``` cpp
8221
+ namespace std::ranges {
8222
+ template<input_range V>
8223
+ requires view<V>
8224
+ template<bool Const>
8225
+ class stride_view<V>::iterator {
8226
+ using Parent = maybe-const<Const, stride_view>; // exposition only
8227
+ using Base = maybe-const<Const, V>; // exposition only
8228
+
8229
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
8230
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
8231
+ range_difference_t<Base> stride_ = 0; // exposition only
8232
+ range_difference_t<Base> missing_ = 0; // exposition only
8233
+
8234
+ constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only
8235
+ range_difference_t<Base> missing = 0);
8236
+ public:
8237
+ using difference_type = range_difference_t<Base>;
8238
+ using value_type = range_value_t<Base>;
8239
+ using iterator_concept = see below;
8240
+ using iterator_category = see below; // not always present
8241
+
8242
+ iterator() requires default_initializable<iterator_t<Base>> = default;
8243
+
8244
+ constexpr iterator(iterator<!Const> other)
8245
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
8246
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
8247
+
8248
+ constexpr iterator_t<Base> base() &&;
8249
+ constexpr const iterator_t<Base>& base() const & noexcept;
8250
+
8251
+ constexpr decltype(auto) operator*() const { return *current_; }
8252
+
8253
+ constexpr iterator& operator++();
8254
+ constexpr void operator++(int);
8255
+ constexpr iterator operator++(int) requires forward_range<Base>;
8256
+
8257
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
8258
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
8259
+
8260
+ constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
8261
+ constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
8262
+
8263
+ constexpr decltype(auto) operator[](difference_type n) const
8264
+ requires random_access_range<Base>
8265
+ { return *(*this + n); }
8266
+
8267
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
8268
+
8269
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
8270
+ requires equality_comparable<iterator_t<Base>>;
8271
+
8272
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
8273
+ requires random_access_range<Base>;
8274
+
8275
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
8276
+ requires random_access_range<Base>;
8277
+
8278
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
8279
+ requires random_access_range<Base>;
8280
+
8281
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
8282
+ requires random_access_range<Base>;
8283
+
8284
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8285
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
8286
+
8287
+ friend constexpr iterator operator+(const iterator& x, difference_type n)
8288
+ requires random_access_range<Base>;
8289
+ friend constexpr iterator operator+(difference_type n, const iterator& x)
8290
+ requires random_access_range<Base>;
8291
+ friend constexpr iterator operator-(const iterator& x, difference_type n)
8292
+ requires random_access_range<Base>;
8293
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8294
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
8295
+
8296
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
8297
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
8298
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
8299
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
8300
+
8301
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
8302
+ noexcept(noexcept(ranges::iter_move(i.current_)));
8303
+
8304
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
8305
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
8306
+ requires indirectly_swappable<iterator_t<Base>>;
8307
+ };
8308
+ }
8309
+ ```
8310
+
8311
+ `iterator::iterator_concept` is defined as follows:
8312
+
8313
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
8314
+ denotes `random_access_iterator_tag`.
8315
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
8316
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
8317
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
8318
+ denotes `forward_iterator_tag`.
8319
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
8320
+
8321
+ The member *typedef-name* `iterator_category` is defined if and only if
8322
+ *`Base`* models `forward_range`. In that case,
8323
+ `iterator::iterator_category` is defined as follows:
8324
+
8325
+ - Let `C` denote the type
8326
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
8327
+ - If `C` models `derived_from<random_access_iterator_tag>`, then
8328
+ `iterator_category` denotes `random_access_iterator_tag`.
8329
+ - Otherwise, `iterator_category` denotes `C`.
8330
+
8331
+ ``` cpp
8332
+ constexpr iterator(Parent* parent, iterator_t<Base> current,
8333
+ range_difference_t<Base> missing = 0);
8334
+ ```
8335
+
8336
+ *Effects:* Initializes *current\_* with `std::move(current)`, *end\_*
8337
+ with `ranges::end(parent->`*`base_`*`)`, *stride\_* with
8338
+ `parent->`*`stride_`*, and *missing\_* with `missing`.
8339
+
8340
+ ``` cpp
8341
+ constexpr iterator(iterator<!Const> i)
8342
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
8343
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
8344
+ ```
8345
+
8346
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`,
8347
+ *end\_* with `std::move(i.`*`end_`*`)`, *stride\_* with `i.`*`stride_`*,
8348
+ and *missing\_* with `i.`*`missing_`*.
8349
+
8350
+ ``` cpp
8351
+ constexpr iterator_t<Base> base() &&;
8352
+ ```
8353
+
8354
+ *Returns:* `std::move(`*`current_`*`)`.
8355
+
8356
+ ``` cpp
8357
+ constexpr const iterator_t<Base>& base() const & noexcept;
8358
+ ```
8359
+
8360
+ *Returns:* *current\_*.
8361
+
8362
+ ``` cpp
8363
+ constexpr iterator& operator++();
8364
+ ```
8365
+
8366
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
8367
+
8368
+ *Effects:* Equivalent to:
8369
+
8370
+ ``` cpp
8371
+ missing_ = ranges::advance(current_, stride_, end_);
8372
+ return *this;
8373
+ ```
8374
+
8375
+ ``` cpp
8376
+ constexpr void operator++(int);
8377
+ ```
8378
+
8379
+ *Effects:* Equivalent to: `++*this;`
8380
+
8381
+ ``` cpp
8382
+ constexpr iterator operator++(int) requires forward_range<Base>;
8383
+ ```
8384
+
8385
+ *Effects:* Equivalent to:
8386
+
8387
+ ``` cpp
8388
+ auto tmp = *this;
8389
+ ++*this;
8390
+ return tmp;
8391
+ ```
8392
+
8393
+ ``` cpp
8394
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
8395
+ ```
8396
+
8397
+ *Effects:* Equivalent to:
8398
+
8399
+ ``` cpp
8400
+ ranges::advance(current_, missing_ - stride_);
8401
+ missing_ = 0;
8402
+ return *this;
8403
+ ```
8404
+
8405
+ ``` cpp
8406
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
8407
+ ```
8408
+
8409
+ *Effects:* Equivalent to:
8410
+
8411
+ ``` cpp
8412
+ auto tmp = *this;
8413
+ --*this;
8414
+ return tmp;
8415
+ ```
8416
+
8417
+ ``` cpp
8418
+ constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
8419
+ ```
8420
+
8421
+ *Preconditions:* If `n` is positive,
8422
+ `ranges::distance(`*`current_`*`, `*`end_`*`) > `*`stride_`*` * (n - 1)`
8423
+ is `true`.
8424
+
8425
+ [*Note 1*: If `n` is negative, the *Effects* paragraph implies a
8426
+ precondition. — *end note*]
8427
+
8428
+ *Effects:* Equivalent to:
8429
+
8430
+ ``` cpp
8431
+ if (n > 0) {
8432
+ ranges::advance(current_, stride_ * (n - 1));
8433
+ missing_ = ranges::advance(current_, stride_, end_);
8434
+ } else if (n < 0) {
8435
+ ranges::advance(current_, stride_ * n + missing_);
8436
+ missing_ = 0;
8437
+ }
8438
+ return *this;
8439
+ ```
8440
+
8441
+ ``` cpp
8442
+ constexpr iterator& operator-=(difference_type x)
8443
+ requires random_access_range<Base>;
8444
+ ```
8445
+
8446
+ *Effects:* Equivalent to: `return *this += -x;`
8447
+
8448
+ ``` cpp
8449
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
8450
+ ```
8451
+
8452
+ *Returns:* `x.`*`current_`*` == x.`*`end_`*.
8453
+
8454
+ ``` cpp
8455
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
8456
+ requires equality_comparable<iterator_t<Base>>;
8457
+ ```
8458
+
8459
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
8460
+
8461
+ ``` cpp
8462
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
8463
+ requires random_access_range<Base>;
8464
+ ```
8465
+
8466
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
8467
+
8468
+ ``` cpp
8469
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
8470
+ requires random_access_range<Base>;
8471
+ ```
8472
+
8473
+ *Effects:* Equivalent to: `return y < x;`
8474
+
8475
+ ``` cpp
8476
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
8477
+ requires random_access_range<Base>;
8478
+ ```
8479
+
8480
+ *Effects:* Equivalent to: `return !(y < x);`
8481
+
8482
+ ``` cpp
8483
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
8484
+ requires random_access_range<Base>;
8485
+ ```
8486
+
8487
+ *Effects:* Equivalent to: `return !(x < y);`
8488
+
8489
+ ``` cpp
8490
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8491
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
8492
+ ```
8493
+
8494
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
8495
+
8496
+ ``` cpp
8497
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
8498
+ requires random_access_range<Base>;
8499
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
8500
+ requires random_access_range<Base>;
8501
+ ```
8502
+
8503
+ *Effects:* Equivalent to:
8504
+
8505
+ ``` cpp
8506
+ auto r = i;
8507
+ r += n;
8508
+ return r;
8509
+ ```
8510
+
8511
+ ``` cpp
8512
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
8513
+ requires random_access_range<Base>;
8514
+ ```
8515
+
8516
+ *Effects:* Equivalent to:
8517
+
8518
+ ``` cpp
8519
+ auto r = i;
8520
+ r -= n;
8521
+ return r;
8522
+ ```
8523
+
8524
+ ``` cpp
8525
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8526
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
8527
+ ```
8528
+
8529
+ *Returns:* Let `N` be `(x.`*`current_`*` - y.`*`current_`*`)`.
8530
+
8531
+ - If *Base* models `forward_range`,
8532
+ `(N + x.`*`missing_`*` - y.`*`missing_`*`) / x.`*`stride_`*.
8533
+ - Otherwise, if `N` is negative, `-`*`div-ceil`*`(-N, x.`*`stride_`*`)`.
8534
+ - Otherwise, *`div-ceil`*`(N, x.`*`stride_`*`)`.
8535
+
8536
+ ``` cpp
8537
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
8538
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
8539
+ ```
8540
+
8541
+ *Returns:*
8542
+ *`div-ceil`*`(x.`*`end_`*` - x.`*`current_`*`, x.`*`stride_`*`)`.
8543
+
8544
+ ``` cpp
8545
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
8546
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
8547
+ ```
8548
+
8549
+ *Effects:* Equivalent to: `return -(y - x);`
8550
+
8551
+ ``` cpp
8552
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
8553
+ noexcept(noexcept(ranges::iter_move(i.current_)));
8554
+ ```
8555
+
8556
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
8557
+
8558
+ ``` cpp
8559
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
8560
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
8561
+ requires indirectly_swappable<iterator_t<Base>>;
8562
+ ```
8563
+
8564
+ *Effects:* Equivalent to:
8565
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`);`
8566
+
8567
+ ### Cartesian product view <a id="range.cartesian">[[range.cartesian]]</a>
8568
+
8569
+ #### Overview <a id="range.cartesian.overview">[[range.cartesian.overview]]</a>
8570
+
8571
+ `cartesian_product_view` takes any non-zero number of ranges n and
8572
+ produces a view of tuples calculated by the n-ary cartesian product of
8573
+ the provided ranges.
8574
+
8575
+ The name `views::cartesian_product` denotes a customization point object
8576
+ [[customization.point.object]]. Given a pack of subexpressions `Es`, the
8577
+ expression `views::cartesian_product(Es...)` is expression-equivalent to
8578
+
8579
+ - `views::single(tuple())` if `Es` is an empty pack,
8580
+ - otherwise,
8581
+ `cartesian_product_view<views::all_t<decltype((Es))>...>(Es...)`.
8582
+
8583
+ [*Example 1*:
8584
+
8585
+ ``` cpp
8586
+ vector<int> v { 0, 1, 2 };
8587
+ for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) {
8588
+ cout << a << ' ' << b << ' ' << c << '\n';
8589
+ }
8590
+ // The above prints
8591
+ // 0 0 0
8592
+ // 0 0 1
8593
+ // 0 0 2
8594
+ // 0 1 0
8595
+ // 0 1 1
8596
+ // ...
8597
+ ```
8598
+
8599
+ — *end example*]
8600
+
8601
+ #### Class template `cartesian_product_view` <a id="range.cartesian.view">[[range.cartesian.view]]</a>
8602
+
8603
+ ``` cpp
8604
+ namespace std::ranges {
8605
+ template<bool Const, class First, class... Vs>
8606
+ concept cartesian-product-is-random-access = // exposition only
8607
+ (random_access_range<maybe-const<Const, First>> && ... &&
8608
+ (random_access_range<maybe-const<Const, Vs>>
8609
+ && sized_range<maybe-const<Const, Vs>>));
8610
+
8611
+ template<class R>
8612
+ concept cartesian-product-common-arg = // exposition only
8613
+ common_range<R> || (sized_range<R> && random_access_range<R>);
8614
+
8615
+ template<bool Const, class First, class... Vs>
8616
+ concept cartesian-product-is-bidirectional = // exposition only
8617
+ (bidirectional_range<maybe-const<Const, First>> && ... &&
8618
+ (bidirectional_range<maybe-const<Const, Vs>>
8619
+ && cartesian-product-common-arg<maybe-const<Const, Vs>>));
8620
+
8621
+ template<class First, class... Vs>
8622
+ concept cartesian-product-is-common = // exposition only
8623
+ cartesian-product-common-arg<First>;
8624
+
8625
+ template<class... Vs>
8626
+ concept cartesian-product-is-sized = // exposition only
8627
+ (sized_range<Vs> && ...);
8628
+
8629
+ template<bool Const, template<class> class FirstSent, class First, class... Vs>
8630
+ concept cartesian-is-sized-sentinel = // exposition only
8631
+ (sized_sentinel_for<FirstSent<maybe-const<Const, First>>,
8632
+ iterator_t<maybe-const<Const, First>>> && ...
8633
+ && (sized_range<maybe-const<Const, Vs>>
8634
+ && sized_sentinel_for<iterator_t<maybe-const<Const, Vs>>,
8635
+ iterator_t<maybe-const<Const, Vs>>>));
8636
+
8637
+ template<cartesian-product-common-arg R>
8638
+ constexpr auto cartesian-common-arg-end(R& r) { // exposition only
8639
+ if constexpr (common_range<R>) {
8640
+ return ranges::end(r);
8641
+ } else {
8642
+ return ranges::begin(r) + ranges::distance(r);
8643
+ }
8644
+ }
8645
+
8646
+ template<input_range First, forward_range... Vs>
8647
+ requires (view<First> && ... && view<Vs>)
8648
+ class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {
8649
+ private:
8650
+ tuple<First, Vs...> bases_; // exposition only
8651
+ // [range.cartesian.iterator], class template cartesian_product_view::iterator
8652
+ template<bool Const> class iterator; // exposition only
8653
+
8654
+ public:
8655
+ constexpr cartesian_product_view() = default;
8656
+ constexpr explicit cartesian_product_view(First first_base, Vs... bases);
8657
+
8658
+ constexpr iterator<false> begin()
8659
+ requires (!simple-view<First> || ... || !simple-view<Vs>);
8660
+ constexpr iterator<true> begin() const
8661
+ requires (range<const First> && ... && range<const Vs>);
8662
+
8663
+ constexpr iterator<false> end()
8664
+ requires ((!simple-view<First> || ... || !simple-view<Vs>) &&
8665
+ cartesian-product-is-common<First, Vs...>);
8666
+ constexpr iterator<true> end() const
8667
+ requires cartesian-product-is-common<const First, const Vs...>;
8668
+ constexpr default_sentinel_t end() const noexcept;
8669
+
8670
+ constexpr see below size()
8671
+ requires cartesian-product-is-sized<First, Vs...>;
8672
+ constexpr see below size() const
8673
+ requires cartesian-product-is-sized<const First, const Vs...>;
8674
+ };
8675
+
8676
+ template<class... Vs>
8677
+ cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>;
8678
+ }
8679
+ ```
8680
+
8681
+ ``` cpp
8682
+ constexpr explicit cartesian_product_view(First first_base, Vs... bases);
8683
+ ```
8684
+
8685
+ *Effects:* Initializes *bases\_* with
8686
+ `std::move(first_base), std::move(bases)...`.
8687
+
8688
+ ``` cpp
8689
+ constexpr iterator<false> begin()
8690
+ requires (!simple-view<First> || ... || !simple-view<Vs>);
8691
+ ```
8692
+
8693
+ *Effects:* Equivalent to:
8694
+
8695
+ ``` cpp
8696
+ return iterator<false>(*this, tuple-transform(ranges::begin, bases_));
8697
+ ```
8698
+
8699
+ ``` cpp
8700
+ constexpr iterator<true> begin() const
8701
+ requires (range<const First> && ... && range<const Vs>);
8702
+ ```
8703
+
8704
+ *Effects:* Equivalent to:
8705
+
8706
+ ``` cpp
8707
+ return iterator<true>(*this, tuple-transform(ranges::begin, bases_));
8708
+ ```
8709
+
8710
+ ``` cpp
8711
+ constexpr iterator<false> end()
8712
+ requires ((!simple-view<First> || ... || !simple-view<Vs>)
8713
+ && cartesian-product-is-common<First, Vs...>);
8714
+ constexpr iterator<true> end() const
8715
+ requires cartesian-product-is-common<const First, const Vs...>;
8716
+ ```
8717
+
8718
+ Let:
8719
+
8720
+ - *is-const* be `true` for the const-qualified overload, and `false`
8721
+ otherwise;
8722
+ - *is-empty* be `true` if the expression `ranges::empty(rng)` is `true`
8723
+ for any `rng` among the underlying ranges except the first one and
8724
+ `false` otherwise; and
8725
+ - *`begin-or-first-end`*`(rng)` be expression-equivalent to
8726
+ *`is-empty`*` ? ranges::begin(rng) : `*`cartesian-common-arg-end`*`(rng)`
8727
+ if `rng` is the first underlying range and `ranges::begin(rng)`
8728
+ otherwise.
8729
+
8730
+ *Effects:* Equivalent to:
8731
+
8732
+ ``` cpp
8733
+ iterator<is-const> it(*this, tuple-transform(
8734
+ [](auto& rng){ return begin-or-first-end(rng); }, bases_));
8735
+ return it;
8736
+ ```
8737
+
8738
+ ``` cpp
8739
+ constexpr default_sentinel_t end() const noexcept;
8740
+ ```
8741
+
8742
+ *Returns:* `default_sentinel`.
8743
+
8744
+ ``` cpp
8745
+ constexpr see below size()
8746
+ requires cartesian-product-is-sized<First, Vs...>;
8747
+ constexpr see below size() const
8748
+ requires cartesian-product-is-sized<const First, const Vs...>;
8749
+ ```
8750
+
8751
+ The return type is an *implementation-defined* unsigned-integer-like
8752
+ type.
8753
+
8754
+ *Recommended practice:* The return type should be the smallest
8755
+ unsigned-integer-like type that is sufficiently wide to store the
8756
+ product of the maximum sizes of all the underlying ranges, if such a
8757
+ type exists.
8758
+
8759
+ Let p be the product of the sizes of all the ranges in *bases\_*.
8760
+
8761
+ *Preconditions:* p can be represented by the return type.
8762
+
8763
+ *Returns:* p.
8764
+
8765
+ #### Class template `cartesian_product_view::iterator` <a id="range.cartesian.iterator">[[range.cartesian.iterator]]</a>
8766
+
8767
+ ``` cpp
8768
+ namespace std::ranges {
8769
+ template<input_range First, forward_range... Vs>
8770
+ requires (view<First> && ... && view<Vs>)
8771
+ template<bool Const>
8772
+ class cartesian_product_view<First, Vs...>::iterator {
8773
+ public:
8774
+ using iterator_category = input_iterator_tag;
8775
+ using iterator_concept = see below;
8776
+ using value_type = tuple<range_value_t<maybe-const<Const, First>>,
8777
+ range_value_t<maybe-const<Const, Vs>>...>;
8778
+ using reference = tuple<range_reference_t<maybe-const<Const, First>>,
8779
+ range_reference_t<maybe-const<Const, Vs>>...>;
8780
+ using difference_type = see below;
8781
+
8782
+ iterator() = default;
8783
+
8784
+ constexpr iterator(iterator<!Const> i) requires Const &&
8785
+ (convertible_to<iterator_t<First>, iterator_t<const First>> &&
8786
+ ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>);
8787
+
8788
+ constexpr auto operator*() const;
8789
+ constexpr iterator& operator++();
8790
+ constexpr void operator++(int);
8791
+ constexpr iterator operator++(int) requires forward_range<maybe-const<Const, First>>;
8792
+
8793
+ constexpr iterator& operator--()
8794
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
8795
+ constexpr iterator operator--(int)
8796
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
8797
+
8798
+ constexpr iterator& operator+=(difference_type x)
8799
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
8800
+ constexpr iterator& operator-=(difference_type x)
8801
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
8802
+
8803
+ constexpr reference operator[](difference_type n) const
8804
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
8805
+
8806
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
8807
+ requires equality_comparable<iterator_t<maybe-const<Const, First>>>;
8808
+
8809
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
8810
+
8811
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8812
+ requires all-random-access<Const, First, Vs...>;
8813
+
8814
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
8815
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
8816
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
8817
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
8818
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
8819
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
8820
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8821
+ requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
8822
+
8823
+ friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
8824
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
8825
+ friend constexpr difference_type operator-(default_sentinel_t, const iterator& i)
8826
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
8827
+
8828
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
8829
+
8830
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
8831
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, First>>> && ... &&
8832
+ indirectly_swappable<iterator_t<maybe-const<Const, Vs>>>);
8833
+
8834
+ private:
8835
+ using Parent = maybe-const<Const, cartesian_product_view>; // exposition only
8836
+ Parent* parent_ = nullptr; // exposition only
8837
+ tuple<iterator_t<maybe-const<Const, First>>,
8838
+ iterator_t<maybe-const<Const, Vs>>...> current_; // exposition only
8839
+
8840
+ template<size_t N = sizeof...(Vs)>
8841
+ constexpr void next(); // exposition only
8842
+
8843
+ template<size_t N = sizeof...(Vs)>
8844
+ constexpr void prev(); // exposition only
8845
+
8846
+ template<class Tuple>
8847
+ constexpr difference_type distance-from(const Tuple& t) const; // exposition only
8848
+
8849
+ constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>,
8850
+ iterator_t<maybe-const<Const, Vs>>...> current); // exposition only
8851
+ };
8852
+ }
8853
+ ```
8854
+
8855
+ `iterator::iterator_concept` is defined as follows:
8856
+
8857
+ - If `cartesian-product-is-random-access<Const, First, Vs...>` is
8858
+ modeled, then `iterator_concept` denotes `random_access_iterator_tag`.
8859
+ - Otherwise, if
8860
+ `cartesian-product-is-bidirectional<Const, First, Vs...>` is modeled,
8861
+ then `iterator_concept` denotes `bidirectional_iterator_tag`.
8862
+ - Otherwise, if `maybe-const<Const, First>` models `forward_range`, then
8863
+ `iterator_concept` denotes `forward_iterator_tag`.
8864
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
8865
+
8866
+ `iterator::difference_type` is an *implementation-defined*
8867
+ signed-integer-like type.
8868
+
8869
+ *Recommended practice:* `iterator::difference_type` should be the
8870
+ smallest signed-integer-like type that is sufficiently wide to store the
8871
+ product of the maximum sizes of all underlying ranges if such a type
8872
+ exists.
8873
+
8874
+ ``` cpp
8875
+ template<size_t N = sizeof...(Vs)>
8876
+ constexpr void next();
8877
+ ```
8878
+
8879
+ *Effects:* Equivalent to:
8880
+
8881
+ ``` cpp
8882
+ auto& it = std::get<N>(current_);
8883
+ ++it;
8884
+ if constexpr (N > 0) {
8885
+ if (it == ranges::end(std::get<N>(parent_->bases_))) {
8886
+ it = ranges::begin(std::get<N>(parent_->bases_));
8887
+ next<N - 1>();
8888
+ }
8889
+ }
8890
+ ```
8891
+
8892
+ ``` cpp
8893
+ template<size_t N = sizeof...(Vs)>
8894
+ constexpr void prev();
8895
+ ```
8896
+
8897
+ *Effects:* Equivalent to:
8898
+
8899
+ ``` cpp
8900
+ auto& it = std::get<N>(current_);
8901
+ if constexpr (N > 0) {
8902
+ if (it == ranges::begin(std::get<N>(parent_->bases_))) {
8903
+ it = cartesian-common-arg-end(std::get<N>(parent_->bases_));
8904
+ prev<N - 1>();
8905
+ }
8906
+ }
8907
+ --it;
8908
+ ```
8909
+
8910
+ ``` cpp
8911
+ template<class Tuple>
8912
+ constexpr difference_type distance-from(const Tuple& t) const;
8913
+ ```
8914
+
8915
+ Let:
8916
+
8917
+ - scaled-size(N) be the product of
8918
+ `static_cast<difference_type>(ranges::size(std::get<`N`>(`*`parent_`*`->`*`bases_`*`)))`
8919
+ and scaled-size(N+1) if N ≤ `sizeof...(Vs)`, otherwise
8920
+ `static_cast<difference_type>(1)`;
8921
+ - scaled-distance(N) be the product of
8922
+ `static_cast<difference_type>(std::get<`N`>(`*`current_`*`) - std::get<`N`>(t))`
8923
+ and scaled-size(N+1); and
8924
+ - *scaled-sum* be the sum of scaled-distance(N) for every integer
8925
+ 0 ≤ N ≤ `sizeof...(Vs)`.
8926
+
8927
+ *Preconditions:* *scaled-sum* can be represented by `difference_type`.
8928
+
8929
+ *Returns:* *scaled-sum*.
8930
+
8931
+ ``` cpp
8932
+ constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>,
8933
+ iterator_t<maybe-const<Const, Vs>>...> current);
8934
+ ```
8935
+
8936
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and
8937
+ *current\_* with `std::move(current)`.
8938
+
8939
+ ``` cpp
8940
+ constexpr iterator(iterator<!Const> i) requires Const &&
8941
+ (convertible_to<iterator_t<First>, iterator_t<const First>> &&
8942
+ ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>);
8943
+ ```
8944
+
8945
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *current\_*
8946
+ with `std::move(i.`*`current_`*`)`.
8947
+
8948
+ ``` cpp
8949
+ constexpr auto operator*() const;
8950
+ ```
8951
+
8952
+ *Effects:* Equivalent to:
8953
+
8954
+ ``` cpp
8955
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
8956
+ ```
8957
+
8958
+ ``` cpp
8959
+ constexpr iterator& operator++();
8960
+ ```
8961
+
8962
+ *Effects:* Equivalent to:
8963
+
8964
+ ``` cpp
8965
+ next();
8966
+ return *this;
8967
+ ```
8968
+
8969
+ ``` cpp
8970
+ constexpr void operator++(int);
8971
+ ```
8972
+
8973
+ *Effects:* Equivalent to `++*this`.
8974
+
8975
+ ``` cpp
8976
+ constexpr iterator operator++(int) requires forward_range<maybe-const<Const, First>>;
8977
+ ```
8978
+
8979
+ *Effects:* Equivalent to:
8980
+
8981
+ ``` cpp
8982
+ auto tmp = *this;
8983
+ ++*this;
8984
+ return tmp;
8985
+ ```
8986
+
8987
+ ``` cpp
8988
+ constexpr iterator& operator--()
8989
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
8990
+ ```
8991
+
8992
+ *Effects:* Equivalent to:
8993
+
8994
+ ``` cpp
8995
+ prev();
8996
+ return *this;
8997
+ ```
8998
+
8999
+ ``` cpp
9000
+ constexpr iterator operator--(int)
9001
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
9002
+ ```
9003
+
9004
+ *Effects:* Equivalent to:
9005
+
9006
+ ``` cpp
9007
+ auto tmp = *this;
9008
+ --*this;
9009
+ return tmp;
9010
+ ```
9011
+
9012
+ ``` cpp
9013
+ constexpr iterator& operator+=(difference_type x)
9014
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
9015
+ ```
9016
+
9017
+ Let `orig` be the value of `*this` before the call.
9018
+
9019
+ Let `ret` be:
9020
+
9021
+ - If `x > 0`, the value of `*this` had *next* been called `x` times.
9022
+ - Otherwise, if `x < 0`, the value of `*this` had *prev* been called
9023
+ `-x` times.
9024
+ - Otherwise, `orig`.
9025
+
9026
+ *Preconditions:* `x` is in the range
9027
+ $[\texttt{ranges::distance(*this, ranges::begin(*\textit{parent_}))},$
9028
+ $\texttt{ranges::distance(*this, ranges::end(*\textit{parent_}))}]$.
9029
+
9030
+ *Effects:* Sets the value of `*this` to `ret`.
9031
+
9032
+ *Returns:* `*this`.
9033
+
9034
+ *Complexity:* Constant.
9035
+
9036
+ ``` cpp
9037
+ constexpr iterator& operator-=(difference_type x)
9038
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
9039
+ ```
9040
+
9041
+ *Effects:* Equivalent to:
9042
+
9043
+ ``` cpp
9044
+ *this += -x;
9045
+ return *this;
9046
+ ```
9047
+
9048
+ ``` cpp
9049
+ constexpr reference operator[](difference_type n) const
9050
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
9051
+ ```
9052
+
9053
+ *Effects:* Equivalent to: `return *((*this) + n);`
9054
+
9055
+ ``` cpp
9056
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
9057
+ requires equality_comparable<iterator_t<maybe-const<Const, First>>>;
9058
+ ```
9059
+
9060
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
9061
+
9062
+ ``` cpp
9063
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
9064
+ ```
9065
+
9066
+ *Returns:* `true` if
9067
+ `std::get<`i`>(x.`*`current_`*`) == ranges::end(std::get<`i`>(x.`*`parent_`*`->`*`bases_`*`))`
9068
+ is `true` for any integer 0 ≤ i ≤ `sizeof...(Vs)`; otherwise, `false`.
9069
+
9070
+ ``` cpp
9071
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
9072
+ requires all-random-access<Const, First, Vs...>;
9073
+ ```
9074
+
9075
+ *Effects:* Equivalent to:
9076
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
9077
+
9078
+ ``` cpp
9079
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
9080
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
9081
+ ```
9082
+
9083
+ *Effects:* Equivalent to: `return `*`iterator`*`(x) += y;`
9084
+
9085
+ ``` cpp
9086
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
9087
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
9088
+ ```
9089
+
9090
+ *Effects:* Equivalent to: `return y + x;`
9091
+
9092
+ ``` cpp
9093
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
9094
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
9095
+ ```
9096
+
9097
+ *Effects:* Equivalent to: `return `*`iterator`*`(x) -= y;`
9098
+
9099
+ ``` cpp
9100
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
9101
+ requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
9102
+ ```
9103
+
9104
+ *Effects:* Equivalent to:
9105
+ `return x.`*`distance-from`*`(y.`*`current_`*`);`
9106
+
9107
+ ``` cpp
9108
+ friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
9109
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
9110
+ ```
9111
+
9112
+ Let *end-tuple* be an object of a type that is a specialization of
9113
+ `tuple`, such that:
9114
+
9115
+ - `std::get<0>(`*`end-tuple`*`)` has the same value as
9116
+ `ranges::end(std::get<0>(i.`*`parent_`*`->`*`bases_`*`))`;
9117
+ - `std::get<`N`>(`*`end-tuple`*`)` has the same value as
9118
+ `ranges::begin(std::get<`N`>(i.`*`parent_`*`->`*`bases_`*`))` for
9119
+ every integer 1 ≤ N ≤ `sizeof...(Vs)`.
9120
+
9121
+ *Effects:* Equivalent to:
9122
+ `return i.`*`distance-from`*`(`*`end-tuple`*`);`
9123
+
9124
+ ``` cpp
9125
+ friend constexpr difference_type operator-(default_sentinel_t s, const iterator& i)
9126
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
9127
+ ```
9128
+
9129
+ *Effects:* Equivalent to: `return -(i - s);`
9130
+
9131
+ ``` cpp
9132
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
9133
+ ```
9134
+
9135
+ *Effects:* Equivalent to:
9136
+ `return `*`tuple-transform`*`(ranges::iter_move, i.`*`current_`*`);`
9137
+
9138
+ *Remarks:* The exception specification is equivalent to the logical of
9139
+ the following expressions:
9140
+
9141
+ - `noexcept(ranges::iter_move(std::get<`N`>(i.`*`current_`*`)))` for
9142
+ every integer 0 ≤ N ≤ `sizeof...(Vs)`,
9143
+ - `is_nothrow_move_constructible_v<range_rvalue_reference_t<`*`maybe-const`*`<Const, T>>>`
9144
+ for every type `T` in `First, Vs...`.
9145
+
9146
+ ``` cpp
9147
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
9148
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, First>>> && ... &&
9149
+ indirectly_swappable<iterator_t<maybe-const<Const, Vs>>>);
9150
+ ```
9151
+
9152
+ *Effects:* For every integer 0 ≤ i ≤ `sizeof...(Vs)`, performs:
9153
+
9154
+ ``` cpp
9155
+ ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
9156
+ ```
9157
+
9158
+ *Remarks:* The exception specification is equivalent to the logical of
9159
+ the following expressions:
9160
+
9161
+ - `noexcept(ranges::iter_swap(std::get<`i`>(l.`*`current_`*`), std::get<`i`>(r.`*`current_`*`)))`
9162
+ for every integer 0 ≤ i ≤ `sizeof...(Vs)`.
9163
+