From Jason Turner

[range.chunk]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp40v2a17h/{from.md → to.md} +778 -0
tmp/tmp40v2a17h/{from.md → to.md} RENAMED
@@ -0,0 +1,778 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Chunk view <a id="range.chunk">[[range.chunk]]</a>
2
+
3
+ #### Overview <a id="range.chunk.overview">[[range.chunk.overview]]</a>
4
+
5
+ `chunk_view` takes a view and a number N and produces a range of views
6
+ that are N-sized non-overlapping successive chunks of the elements of
7
+ the original view, in order. The last view in the range can have fewer
8
+ than N elements.
9
+
10
+ The name `views::chunk` denotes a range adaptor object
11
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
12
+ expression `views::chunk(E, N)` is expression-equivalent to
13
+ `chunk_view(E, N)`.
14
+
15
+ [*Example 1*:
16
+
17
+ ``` cpp
18
+ vector v = {1, 2, 3, 4, 5};
19
+
20
+ for (auto r : v | views::chunk(2)) {
21
+ cout << '[';
22
+ auto sep = "";
23
+ for (auto i : r) {
24
+ cout << sep << i;
25
+ sep = ", ";
26
+ }
27
+ cout << "] ";
28
+ }
29
+ // The above prints [1, 2] [3, 4] [5]
30
+ ```
31
+
32
+ — *end example*]
33
+
34
+ #### Class template `chunk_view` for input ranges <a id="range.chunk.view.input">[[range.chunk.view.input]]</a>
35
+
36
+ ``` cpp
37
+ namespace std::ranges {
38
+ template<class I>
39
+ constexpr I div-ceil(I num, I denom) { // exposition only
40
+ I r = num / denom;
41
+ if (num % denom)
42
+ ++r;
43
+ return r;
44
+ }
45
+
46
+ template<view V>
47
+ requires input_range<V>
48
+ class chunk_view : public view_interface<chunk_view<V>> {
49
+ V base_; // exposition only
50
+ range_difference_t<V> n_; // exposition only
51
+ range_difference_t<V> remainder_ = 0; // exposition only
52
+
53
+ non-propagating-cache<iterator_t<V>> current_; // exposition only
54
+
55
+ // [range.chunk.outer.iter], class chunk_view::outer-iterator
56
+ class outer-iterator; // exposition only
57
+
58
+ // [range.chunk.inner.iter], class chunk_view::inner-iterator
59
+ class inner-iterator; // exposition only
60
+
61
+ public:
62
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
63
+
64
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
65
+ constexpr V base() && { return std::move(base_); }
66
+
67
+ constexpr outer-iterator begin();
68
+ constexpr default_sentinel_t end() const noexcept;
69
+
70
+ constexpr auto size() requires sized_range<V>;
71
+ constexpr auto size() const requires sized_range<const V>;
72
+ };
73
+
74
+ template<class R>
75
+ chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;
76
+ }
77
+ ```
78
+
79
+ ``` cpp
80
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
81
+ ```
82
+
83
+ *Preconditions:* `n > 0` is `true`.
84
+
85
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
86
+ `n`.
87
+
88
+ ``` cpp
89
+ constexpr outer-iterator begin();
90
+ ```
91
+
92
+ *Effects:* Equivalent to:
93
+
94
+ ``` cpp
95
+ current_ = ranges::begin(base_);
96
+ remainder_ = n_;
97
+ return outer-iterator(*this);
98
+ ```
99
+
100
+ ``` cpp
101
+ constexpr default_sentinel_t end() const noexcept;
102
+ ```
103
+
104
+ *Returns:* `default_sentinel`.
105
+
106
+ ``` cpp
107
+ constexpr auto size() requires sized_range<V>;
108
+ constexpr auto size() const requires sized_range<const V>;
109
+ ```
110
+
111
+ *Effects:* Equivalent to:
112
+
113
+ ``` cpp
114
+ return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
115
+ ```
116
+
117
+ #### Class `chunk_view::outer-iterator` <a id="range.chunk.outer.iter">[[range.chunk.outer.iter]]</a>
118
+
119
+ ``` cpp
120
+ namespace std::ranges {
121
+ template<view V>
122
+ requires input_range<V>
123
+ class chunk_view<V>::outer-iterator {
124
+ chunk_view* parent_; // exposition only
125
+
126
+ constexpr explicit outer-iterator(chunk_view& parent); // exposition only
127
+
128
+ public:
129
+ using iterator_concept = input_iterator_tag;
130
+ using difference_type = range_difference_t<V>;
131
+
132
+ // [range.chunk.outer.value], class chunk_view::outer-iterator::value_type
133
+ struct value_type;
134
+
135
+ outer-iterator(outer-iterator&&) = default;
136
+ outer-iterator& operator=(outer-iterator&&) = default;
137
+
138
+ constexpr value_type operator*() const;
139
+ constexpr outer-iterator& operator++();
140
+ constexpr void operator++(int);
141
+
142
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
143
+
144
+ friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)
145
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
146
+ friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)
147
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
148
+ };
149
+ }
150
+ ```
151
+
152
+ ``` cpp
153
+ constexpr explicit outer-iterator(chunk_view& parent);
154
+ ```
155
+
156
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
157
+
158
+ ``` cpp
159
+ constexpr value_type operator*() const;
160
+ ```
161
+
162
+ *Preconditions:* `*this == default_sentinel` is `false`.
163
+
164
+ *Returns:* `value_type(*`*`parent_`*`)`.
165
+
166
+ ``` cpp
167
+ constexpr outer-iterator& operator++();
168
+ ```
169
+
170
+ *Preconditions:* `*this == default_sentinel` is `false`.
171
+
172
+ *Effects:* Equivalent to:
173
+
174
+ ``` cpp
175
+ ranges::advance(*parent_->current_, parent_->remainder_, ranges::end(parent_->base_));
176
+ parent_->remainder_ = parent_->n_;
177
+ return *this;
178
+ ```
179
+
180
+ ``` cpp
181
+ constexpr void operator++(int);
182
+ ```
183
+
184
+ *Effects:* Equivalent to `++*this`.
185
+
186
+ ``` cpp
187
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
188
+ ```
189
+
190
+ *Effects:* Equivalent to:
191
+
192
+ ``` cpp
193
+ return *x.parent_->current_ == ranges::end(x.parent_->base_) && x.parent_->remainder_ != 0;
194
+ ```
195
+
196
+ ``` cpp
197
+ friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)
198
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
199
+ ```
200
+
201
+ *Effects:* Equivalent to:
202
+
203
+ ``` cpp
204
+ const auto dist = ranges::end(x.parent_->base_) - *x.parent_->current_;
205
+ if (dist < x.parent_->remainder_) {
206
+ return dist == 0 ? 0 : 1;
207
+ }
208
+ return div-ceil(dist - x.parent_->remainder_, x.parent_->n_) + 1;
209
+ ```
210
+
211
+ ``` cpp
212
+ friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)
213
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
214
+ ```
215
+
216
+ *Effects:* Equivalent to: `return -(y - x);`
217
+
218
+ #### Class `chunk_view::outer-iterator::value_type` <a id="range.chunk.outer.value">[[range.chunk.outer.value]]</a>
219
+
220
+ ``` cpp
221
+ namespace std::ranges {
222
+ template<view V>
223
+ requires input_range<V>
224
+ struct chunk_view<V>::outer-iterator::value_type : view_interface<value_type> {
225
+ private:
226
+ chunk_view* parent_; // exposition only
227
+
228
+ constexpr explicit value_type(chunk_view& parent); // exposition only
229
+
230
+ public:
231
+ constexpr inner-iterator begin() const noexcept;
232
+ constexpr default_sentinel_t end() const noexcept;
233
+
234
+ constexpr auto size() const
235
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
236
+ };
237
+ }
238
+ ```
239
+
240
+ ``` cpp
241
+ constexpr explicit value_type(chunk_view& parent);
242
+ ```
243
+
244
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
245
+
246
+ ``` cpp
247
+ constexpr inner-iterator begin() const noexcept;
248
+ ```
249
+
250
+ *Returns:* *`inner-iterator`*`(*`*`parent_`*`)`.
251
+
252
+ ``` cpp
253
+ constexpr default_sentinel_t end() const noexcept;
254
+ ```
255
+
256
+ *Returns:* `default_sentinel`.
257
+
258
+ ``` cpp
259
+ constexpr auto size() const
260
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
261
+ ```
262
+
263
+ *Effects:* Equivalent to:
264
+
265
+ ``` cpp
266
+ return to-unsigned-like(ranges::min(parent_->remainder_,
267
+ ranges::end(parent_->base_) - *parent_->current_));
268
+ ```
269
+
270
+ #### Class `chunk_view::inner-iterator` <a id="range.chunk.inner.iter">[[range.chunk.inner.iter]]</a>
271
+
272
+ ``` cpp
273
+ namespace std::ranges {
274
+ template<view V>
275
+ requires input_range<V>
276
+ class chunk_view<V>::inner-iterator {
277
+ chunk_view* parent_; // exposition only
278
+
279
+ constexpr explicit inner-iterator(chunk_view& parent) noexcept; // exposition only
280
+
281
+ public:
282
+ using iterator_concept = input_iterator_tag;
283
+ using difference_type = range_difference_t<V>;
284
+ using value_type = range_value_t<V>;
285
+
286
+ inner-iterator(inner-iterator&&) = default;
287
+ inner-iterator& operator=(inner-iterator&&) = default;
288
+
289
+ constexpr const iterator_t<V>& base() const &;
290
+
291
+ constexpr range_reference_t<V> operator*() const;
292
+ constexpr inner-iterator& operator++();
293
+ constexpr void operator++(int);
294
+
295
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
296
+
297
+ friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)
298
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
299
+ friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)
300
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
301
+
302
+ friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i)
303
+ noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
304
+
305
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
306
+ noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))
307
+ requires indirectly_swappable<iterator_t<V>>;
308
+ };
309
+ }
310
+ ```
311
+
312
+ ``` cpp
313
+ constexpr explicit inner-iterator(chunk_view& parent) noexcept;
314
+ ```
315
+
316
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
317
+
318
+ ``` cpp
319
+ constexpr const iterator_t<V>& base() const &;
320
+ ```
321
+
322
+ *Effects:* Equivalent to: `return *`*`parent_`*`->`*`current_`*`;`
323
+
324
+ ``` cpp
325
+ constexpr range_reference_t<V> operator*() const;
326
+ ```
327
+
328
+ *Preconditions:* `*this == default_sentinel` is `false`.
329
+
330
+ *Effects:* Equivalent to: `return **`*`parent_`*`->`*`current_`*`;`
331
+
332
+ ``` cpp
333
+ constexpr inner-iterator& operator++();
334
+ ```
335
+
336
+ *Preconditions:* `*this == default_sentinel` is `false`.
337
+
338
+ *Effects:* Equivalent to:
339
+
340
+ ``` cpp
341
+ ++*parent_->current_;
342
+ if (*parent_->current_ == ranges::end(parent_->base_))
343
+ parent_->remainder_ = 0;
344
+ else
345
+ --parent_->remainder_;
346
+ return *this;
347
+ ```
348
+
349
+ ``` cpp
350
+ constexpr void operator++(int);
351
+ ```
352
+
353
+ *Effects:* Equivalent to `++*this`.
354
+
355
+ ``` cpp
356
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
357
+ ```
358
+
359
+ *Returns:* `x.`*`parent_`*`->`*`remainder_`*` == 0`.
360
+
361
+ ``` cpp
362
+ friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)
363
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
364
+ ```
365
+
366
+ *Effects:* Equivalent to:
367
+
368
+ ``` cpp
369
+ return ranges::min(x.parent_->remainder_,
370
+ ranges::end(x.parent_->base_) - *x.parent_->current_);
371
+ ```
372
+
373
+ ``` cpp
374
+ friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)
375
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
376
+ ```
377
+
378
+ *Effects:* Equivalent to: `return -(y - x);`
379
+
380
+ ``` cpp
381
+ friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i)
382
+ noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
383
+ ```
384
+
385
+ *Effects:* Equivalent to:
386
+ `return ranges::iter_move(*i.`*`parent_`*`->`*`current_`*`);`
387
+
388
+ ``` cpp
389
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
390
+ noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))
391
+ requires indirectly_swappable<iterator_t<V>>;
392
+ ```
393
+
394
+ *Effects:* Equivalent to:
395
+ `ranges::iter_swap(*x.`*`parent_`*`->`*`current_`*`, *y.`*`parent_`*`->`*`current_`*`);`
396
+
397
+ #### Class template `chunk_view` for forward ranges <a id="range.chunk.view.fwd">[[range.chunk.view.fwd]]</a>
398
+
399
+ ``` cpp
400
+ namespace std::ranges {
401
+ template<view V>
402
+ requires forward_range<V>
403
+ class chunk_view<V> : public view_interface<chunk_view<V>> {
404
+ V base_; // exposition only
405
+ range_difference_t<V> n_; // exposition only
406
+
407
+ // [range.chunk.fwd.iter], class template chunk_view::iterator
408
+ template<bool> class iterator; // exposition only
409
+
410
+ public:
411
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
412
+
413
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
414
+ constexpr V base() && { return std::move(base_); }
415
+
416
+ constexpr auto begin() requires (!simple-view<V>) {
417
+ return iterator<false>(this, ranges::begin(base_));
418
+ }
419
+
420
+ constexpr auto begin() const requires forward_range<const V> {
421
+ return iterator<true>(this, ranges::begin(base_));
422
+ }
423
+
424
+ constexpr auto end() requires (!simple-view<V>) {
425
+ if constexpr (common_range<V> && sized_range<V>) {
426
+ auto missing = (n_ - ranges::distance(base_) % n_) % n_;
427
+ return iterator<false>(this, ranges::end(base_), missing);
428
+ } else if constexpr (common_range<V> && !bidirectional_range<V>) {
429
+ return iterator<false>(this, ranges::end(base_));
430
+ } else {
431
+ return default_sentinel;
432
+ }
433
+ }
434
+
435
+ constexpr auto end() const requires forward_range<const V> {
436
+ if constexpr (common_range<const V> && sized_range<const V>) {
437
+ auto missing = (n_ - ranges::distance(base_) % n_) % n_;
438
+ return iterator<true>(this, ranges::end(base_), missing);
439
+ } else if constexpr (common_range<const V> && !bidirectional_range<const V>) {
440
+ return iterator<true>(this, ranges::end(base_));
441
+ } else {
442
+ return default_sentinel;
443
+ }
444
+ }
445
+
446
+ constexpr auto size() requires sized_range<V>;
447
+ constexpr auto size() const requires sized_range<const V>;
448
+ };
449
+ }
450
+ ```
451
+
452
+ ``` cpp
453
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
454
+ ```
455
+
456
+ *Preconditions:* `n > 0` is `true`.
457
+
458
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
459
+ `n`.
460
+
461
+ ``` cpp
462
+ constexpr auto size() requires sized_range<V>;
463
+ constexpr auto size() const requires sized_range<const V>;
464
+ ```
465
+
466
+ *Effects:* Equivalent to:
467
+
468
+ ``` cpp
469
+ return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
470
+ ```
471
+
472
+ #### Class template `chunk_view::iterator` for forward ranges <a id="range.chunk.fwd.iter">[[range.chunk.fwd.iter]]</a>
473
+
474
+ ``` cpp
475
+ namespace std::ranges {
476
+ template<view V>
477
+ requires forward_range<V>
478
+ template<bool Const>
479
+ class chunk_view<V>::iterator {
480
+ using Parent = maybe-const<Const, chunk_view>; // exposition only
481
+ using Base = maybe-const<Const, V>; // exposition only
482
+
483
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
484
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
485
+ range_difference_t<Base> n_ = 0; // exposition only
486
+ range_difference_t<Base> missing_ = 0; // exposition only
487
+
488
+ constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only
489
+ range_difference_t<Base> missing = 0);
490
+
491
+ public:
492
+ using iterator_category = input_iterator_tag;
493
+ using iterator_concept = see below;
494
+ using value_type = decltype(views::take(subrange(current_, end_), n_));
495
+ using difference_type = range_difference_t<Base>;
496
+
497
+ iterator() = default;
498
+ constexpr iterator(iterator<!Const> i)
499
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
500
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
501
+
502
+ constexpr iterator_t<Base> base() const;
503
+
504
+ constexpr value_type operator*() const;
505
+ constexpr iterator& operator++();
506
+ constexpr iterator operator++(int);
507
+
508
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
509
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
510
+
511
+ constexpr iterator& operator+=(difference_type x)
512
+ requires random_access_range<Base>;
513
+ constexpr iterator& operator-=(difference_type x)
514
+ requires random_access_range<Base>;
515
+
516
+ constexpr value_type operator[](difference_type n) const
517
+ requires random_access_range<Base>;
518
+
519
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
520
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
521
+
522
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
523
+ requires random_access_range<Base>;
524
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
525
+ requires random_access_range<Base>;
526
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
527
+ requires random_access_range<Base>;
528
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
529
+ requires random_access_range<Base>;
530
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
531
+ requires random_access_range<Base> &&
532
+ three_way_comparable<iterator_t<Base>>;
533
+
534
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
535
+ requires random_access_range<Base>;
536
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
537
+ requires random_access_range<Base>;
538
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
539
+ requires random_access_range<Base>;
540
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
541
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
542
+
543
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
544
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
545
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
546
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
547
+ };
548
+ }
549
+ ```
550
+
551
+ `iterator::iterator_concept` is defined as follows:
552
+
553
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
554
+ denotes `random_access_iterator_tag`.
555
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
556
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
557
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
558
+
559
+ ``` cpp
560
+ constexpr iterator(Parent* parent, iterator_t<Base> current,
561
+ range_difference_t<Base> missing = 0);
562
+ ```
563
+
564
+ *Effects:* Initializes *current\_* with `current`, *end\_* with
565
+ `ranges::end(parent->`*`base_`*`)`, *n\_* with `parent->`*`n_`*, and
566
+ *missing\_* with `missing`.
567
+
568
+ ``` cpp
569
+ constexpr iterator(iterator<!Const> i)
570
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
571
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
572
+ ```
573
+
574
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`,
575
+ *end\_* with `std::move(i.`*`end_`*`)`, *n\_* with `i.`*`n_`*, and
576
+ *missing\_* with `i.`*`missing_`*.
577
+
578
+ ``` cpp
579
+ constexpr iterator_t<Base> base() const;
580
+ ```
581
+
582
+ *Returns:* *current\_*.
583
+
584
+ ``` cpp
585
+ constexpr value_type operator*() const;
586
+ ```
587
+
588
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
589
+
590
+ *Returns:*
591
+ `views::take(subrange(`*`current_`*`, `*`end_`*`), `*`n_`*`)`.
592
+
593
+ ``` cpp
594
+ constexpr iterator& operator++();
595
+ ```
596
+
597
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
598
+
599
+ *Effects:* Equivalent to:
600
+
601
+ ``` cpp
602
+ missing_ = ranges::advance(current_, n_, end_);
603
+ return *this;
604
+ ```
605
+
606
+ ``` cpp
607
+ constexpr iterator operator++(int);
608
+ ```
609
+
610
+ *Effects:* Equivalent to:
611
+
612
+ ``` cpp
613
+ auto tmp = *this;
614
+ ++*this;
615
+ return tmp;
616
+ ```
617
+
618
+ ``` cpp
619
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
620
+ ```
621
+
622
+ *Effects:* Equivalent to:
623
+
624
+ ``` cpp
625
+ ranges::advance(current_, missing_ - n_);
626
+ missing_ = 0;
627
+ return *this;
628
+ ```
629
+
630
+ ``` cpp
631
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
632
+ ```
633
+
634
+ *Effects:* Equivalent to:
635
+
636
+ ``` cpp
637
+ auto tmp = *this;
638
+ --*this;
639
+ return tmp;
640
+ ```
641
+
642
+ ``` cpp
643
+ constexpr iterator& operator+=(difference_type x)
644
+ requires random_access_range<Base>;
645
+ ```
646
+
647
+ *Preconditions:* If `x` is positive,
648
+ `ranges::distance(`*`current_`*`, `*`end_`*`) > `*`n_`*` * (x - 1)` is
649
+ `true`.
650
+
651
+ [*Note 1*: If `x` is negative, the *Effects* paragraph implies a
652
+ precondition. — *end note*]
653
+
654
+ *Effects:* Equivalent to:
655
+
656
+ ``` cpp
657
+ if (x > 0) {
658
+ ranges::advance(current_, n_ * (x - 1));
659
+ missing_ = ranges::advance(current_, n_, end_);
660
+ } else if (x < 0) {
661
+ ranges::advance(current_, n_ * x + missing_);
662
+ missing_ = 0;
663
+ }
664
+ return *this;
665
+ ```
666
+
667
+ ``` cpp
668
+ constexpr iterator& operator-=(difference_type x)
669
+ requires random_access_range<Base>;
670
+ ```
671
+
672
+ *Effects:* Equivalent to: `return *this += -x;`
673
+
674
+ ``` cpp
675
+ constexpr value_type operator[](difference_type n) const
676
+ requires random_access_range<Base>;
677
+ ```
678
+
679
+ *Returns:* `*(*this + n)`.
680
+
681
+ ``` cpp
682
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
683
+ ```
684
+
685
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
686
+
687
+ ``` cpp
688
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
689
+ ```
690
+
691
+ *Returns:* `x.`*`current_`*` == x.`*`end_`*.
692
+
693
+ ``` cpp
694
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
695
+ requires random_access_range<Base>;
696
+ ```
697
+
698
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
699
+
700
+ ``` cpp
701
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
702
+ requires random_access_range<Base>;
703
+ ```
704
+
705
+ *Effects:* Equivalent to: `return y < x;`
706
+
707
+ ``` cpp
708
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
709
+ requires random_access_range<Base>;
710
+ ```
711
+
712
+ *Effects:* Equivalent to: `return !(y < x);`
713
+
714
+ ``` cpp
715
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
716
+ requires random_access_range<Base>;
717
+ ```
718
+
719
+ *Effects:* Equivalent to: `return !(x < y);`
720
+
721
+ ``` cpp
722
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
723
+ requires random_access_range<Base> &&
724
+ three_way_comparable<iterator_t<Base>>;
725
+ ```
726
+
727
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
728
+
729
+ ``` cpp
730
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
731
+ requires random_access_range<Base>;
732
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
733
+ requires random_access_range<Base>;
734
+ ```
735
+
736
+ *Effects:* Equivalent to:
737
+
738
+ ``` cpp
739
+ auto r = i;
740
+ r += n;
741
+ return r;
742
+ ```
743
+
744
+ ``` cpp
745
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
746
+ requires random_access_range<Base>;
747
+ ```
748
+
749
+ *Effects:* Equivalent to:
750
+
751
+ ``` cpp
752
+ auto r = i;
753
+ r -= n;
754
+ return r;
755
+ ```
756
+
757
+ ``` cpp
758
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
759
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
760
+ ```
761
+
762
+ *Returns:*
763
+ `(x.`*`current_`*` - y.`*`current_`*` + x.`*`missing_`*` - y.`*`missing_`*`) / x.`*`n_`*.
764
+
765
+ ``` cpp
766
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
767
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
768
+ ```
769
+
770
+ *Returns:* *`div-ceil`*`(x.`*`end_`*` - x.`*`current_`*`, x.`*`n_`*`)`.
771
+
772
+ ``` cpp
773
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
774
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
775
+ ```
776
+
777
+ *Effects:* Equivalent to: `return -(y - x);`
778
+