From Jason Turner

[range.stride]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpqgd45by8/{from.md → to.md} +455 -0
tmp/tmpqgd45by8/{from.md → to.md} RENAMED
@@ -0,0 +1,455 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Stride view <a id="range.stride">[[range.stride]]</a>
2
+
3
+ #### Overview <a id="range.stride.overview">[[range.stride.overview]]</a>
4
+
5
+ `stride_view` presents a view of an underlying sequence, advancing over
6
+ n elements at a time, as opposed to the usual single-step succession.
7
+
8
+ The name `views::stride` denotes a range adaptor object
9
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
10
+ expression `views::stride(E, N)` is expression-equivalent to
11
+ `stride_view(E, N)`.
12
+
13
+ [*Example 1*:
14
+
15
+ ``` cpp
16
+ auto input = views::iota(0, 12) | views::stride(3);
17
+ ranges::copy(input, ostream_iterator<int>(cout, " ")); // prints 0 3 6 9
18
+ ranges::copy(input | views::reverse, ostream_iterator<int>(cout, " ")); // prints 9 6 3 0
19
+ ```
20
+
21
+ — *end example*]
22
+
23
+ #### Class template `stride_view` <a id="range.stride.view">[[range.stride.view]]</a>
24
+
25
+ ``` cpp
26
+ namespace std::ranges {
27
+ template<input_range V>
28
+ requires view<V>
29
+ class stride_view : public view_interface<stride_view<V>> {
30
+ V base_; // exposition only
31
+ range_difference_t<V> stride_; // exposition only
32
+ // [range.stride.iterator], class template stride_view::iterator
33
+ template<bool> class iterator; // exposition only
34
+ public:
35
+ constexpr explicit stride_view(V base, range_difference_t<V> stride);
36
+
37
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
38
+ constexpr V base() && { return std::move(base_); }
39
+
40
+ constexpr range_difference_t<V> stride() const noexcept;
41
+
42
+ constexpr auto begin() requires (!simple-view<V>) {
43
+ return iterator<false>(this, ranges::begin(base_));
44
+ }
45
+
46
+ constexpr auto begin() const requires range<const V> {
47
+ return iterator<true>(this, ranges::begin(base_));
48
+ }
49
+
50
+ constexpr auto end() requires (!simple-view<V>) {
51
+ if constexpr (common_range<V> && sized_range<V> && forward_range<V>) {
52
+ auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_;
53
+ return iterator<false>(this, ranges::end(base_), missing);
54
+ } else if constexpr (common_range<V> && !bidirectional_range<V>) {
55
+ return iterator<false>(this, ranges::end(base_));
56
+ } else {
57
+ return default_sentinel;
58
+ }
59
+ }
60
+
61
+ constexpr auto end() const requires range<const V> {
62
+ if constexpr (common_range<const V> && sized_range<const V> && forward_range<const V>) {
63
+ auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_;
64
+ return iterator<true>(this, ranges::end(base_), missing);
65
+ } else if constexpr (common_range<const V> && !bidirectional_range<const V>) {
66
+ return iterator<true>(this, ranges::end(base_));
67
+ } else {
68
+ return default_sentinel;
69
+ }
70
+ }
71
+
72
+ constexpr auto size() requires sized_range<V>;
73
+ constexpr auto size() const requires sized_range<const V>;
74
+ };
75
+
76
+ template<class R>
77
+ stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;
78
+ }
79
+ ```
80
+
81
+ ``` cpp
82
+ constexpr stride_view(V base, range_difference_t<V> stride);
83
+ ```
84
+
85
+ *Preconditions:* `stride > 0` is `true`.
86
+
87
+ *Effects:* Initializes *base\_* with `std::move(base)` and *stride\_*
88
+ with `stride`.
89
+
90
+ ``` cpp
91
+ constexpr range_difference_t<V> stride() const noexcept;
92
+ ```
93
+
94
+ *Returns:* *stride\_*.
95
+
96
+ ``` cpp
97
+ constexpr auto size() requires sized_range<V>;
98
+ constexpr auto size() const requires sized_range<const V>;
99
+ ```
100
+
101
+ *Effects:* Equivalent to:
102
+
103
+ ``` cpp
104
+ return to-unsigned-like(div-ceil(ranges::distance(base_), stride_));
105
+ ```
106
+
107
+ #### Class template `stride_view::iterator` <a id="range.stride.iterator">[[range.stride.iterator]]</a>
108
+
109
+ ``` cpp
110
+ namespace std::ranges {
111
+ template<input_range V>
112
+ requires view<V>
113
+ template<bool Const>
114
+ class stride_view<V>::iterator {
115
+ using Parent = maybe-const<Const, stride_view>; // exposition only
116
+ using Base = maybe-const<Const, V>; // exposition only
117
+
118
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
119
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
120
+ range_difference_t<Base> stride_ = 0; // exposition only
121
+ range_difference_t<Base> missing_ = 0; // exposition only
122
+
123
+ constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only
124
+ range_difference_t<Base> missing = 0);
125
+ public:
126
+ using difference_type = range_difference_t<Base>;
127
+ using value_type = range_value_t<Base>;
128
+ using iterator_concept = see below;
129
+ using iterator_category = see below; // not always present
130
+
131
+ iterator() requires default_initializable<iterator_t<Base>> = default;
132
+
133
+ constexpr iterator(iterator<!Const> other)
134
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
135
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
136
+
137
+ constexpr iterator_t<Base> base() &&;
138
+ constexpr const iterator_t<Base>& base() const & noexcept;
139
+
140
+ constexpr decltype(auto) operator*() const { return *current_; }
141
+
142
+ constexpr iterator& operator++();
143
+ constexpr void operator++(int);
144
+ constexpr iterator operator++(int) requires forward_range<Base>;
145
+
146
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
147
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
148
+
149
+ constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
150
+ constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
151
+
152
+ constexpr decltype(auto) operator[](difference_type n) const
153
+ requires random_access_range<Base>
154
+ { return *(*this + n); }
155
+
156
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
157
+
158
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
159
+ requires equality_comparable<iterator_t<Base>>;
160
+
161
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
162
+ requires random_access_range<Base>;
163
+
164
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
165
+ requires random_access_range<Base>;
166
+
167
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
168
+ requires random_access_range<Base>;
169
+
170
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
171
+ requires random_access_range<Base>;
172
+
173
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
174
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
175
+
176
+ friend constexpr iterator operator+(const iterator& x, difference_type n)
177
+ requires random_access_range<Base>;
178
+ friend constexpr iterator operator+(difference_type n, const iterator& x)
179
+ requires random_access_range<Base>;
180
+ friend constexpr iterator operator-(const iterator& x, difference_type n)
181
+ requires random_access_range<Base>;
182
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
183
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
184
+
185
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
186
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
187
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
188
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
189
+
190
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
191
+ noexcept(noexcept(ranges::iter_move(i.current_)));
192
+
193
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
194
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
195
+ requires indirectly_swappable<iterator_t<Base>>;
196
+ };
197
+ }
198
+ ```
199
+
200
+ `iterator::iterator_concept` is defined as follows:
201
+
202
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
203
+ denotes `random_access_iterator_tag`.
204
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
205
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
206
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
207
+ denotes `forward_iterator_tag`.
208
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
209
+
210
+ The member *typedef-name* `iterator_category` is defined if and only if
211
+ *`Base`* models `forward_range`. In that case,
212
+ `iterator::iterator_category` is defined as follows:
213
+
214
+ - Let `C` denote the type
215
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
216
+ - If `C` models `derived_from<random_access_iterator_tag>`, then
217
+ `iterator_category` denotes `random_access_iterator_tag`.
218
+ - Otherwise, `iterator_category` denotes `C`.
219
+
220
+ ``` cpp
221
+ constexpr iterator(Parent* parent, iterator_t<Base> current,
222
+ range_difference_t<Base> missing = 0);
223
+ ```
224
+
225
+ *Effects:* Initializes *current\_* with `std::move(current)`, *end\_*
226
+ with `ranges::end(parent->`*`base_`*`)`, *stride\_* with
227
+ `parent->`*`stride_`*, and *missing\_* with `missing`.
228
+
229
+ ``` cpp
230
+ constexpr iterator(iterator<!Const> i)
231
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
232
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
233
+ ```
234
+
235
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`,
236
+ *end\_* with `std::move(i.`*`end_`*`)`, *stride\_* with `i.`*`stride_`*,
237
+ and *missing\_* with `i.`*`missing_`*.
238
+
239
+ ``` cpp
240
+ constexpr iterator_t<Base> base() &&;
241
+ ```
242
+
243
+ *Returns:* `std::move(`*`current_`*`)`.
244
+
245
+ ``` cpp
246
+ constexpr const iterator_t<Base>& base() const & noexcept;
247
+ ```
248
+
249
+ *Returns:* *current\_*.
250
+
251
+ ``` cpp
252
+ constexpr iterator& operator++();
253
+ ```
254
+
255
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
256
+
257
+ *Effects:* Equivalent to:
258
+
259
+ ``` cpp
260
+ missing_ = ranges::advance(current_, stride_, end_);
261
+ return *this;
262
+ ```
263
+
264
+ ``` cpp
265
+ constexpr void operator++(int);
266
+ ```
267
+
268
+ *Effects:* Equivalent to: `++*this;`
269
+
270
+ ``` cpp
271
+ constexpr iterator operator++(int) requires forward_range<Base>;
272
+ ```
273
+
274
+ *Effects:* Equivalent to:
275
+
276
+ ``` cpp
277
+ auto tmp = *this;
278
+ ++*this;
279
+ return tmp;
280
+ ```
281
+
282
+ ``` cpp
283
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
284
+ ```
285
+
286
+ *Effects:* Equivalent to:
287
+
288
+ ``` cpp
289
+ ranges::advance(current_, missing_ - stride_);
290
+ missing_ = 0;
291
+ return *this;
292
+ ```
293
+
294
+ ``` cpp
295
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
296
+ ```
297
+
298
+ *Effects:* Equivalent to:
299
+
300
+ ``` cpp
301
+ auto tmp = *this;
302
+ --*this;
303
+ return tmp;
304
+ ```
305
+
306
+ ``` cpp
307
+ constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
308
+ ```
309
+
310
+ *Preconditions:* If `n` is positive,
311
+ `ranges::distance(`*`current_`*`, `*`end_`*`) > `*`stride_`*` * (n - 1)`
312
+ is `true`.
313
+
314
+ [*Note 1*: If `n` is negative, the *Effects* paragraph implies a
315
+ precondition. — *end note*]
316
+
317
+ *Effects:* Equivalent to:
318
+
319
+ ``` cpp
320
+ if (n > 0) {
321
+ ranges::advance(current_, stride_ * (n - 1));
322
+ missing_ = ranges::advance(current_, stride_, end_);
323
+ } else if (n < 0) {
324
+ ranges::advance(current_, stride_ * n + missing_);
325
+ missing_ = 0;
326
+ }
327
+ return *this;
328
+ ```
329
+
330
+ ``` cpp
331
+ constexpr iterator& operator-=(difference_type x)
332
+ requires random_access_range<Base>;
333
+ ```
334
+
335
+ *Effects:* Equivalent to: `return *this += -x;`
336
+
337
+ ``` cpp
338
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
339
+ ```
340
+
341
+ *Returns:* `x.`*`current_`*` == x.`*`end_`*.
342
+
343
+ ``` cpp
344
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
345
+ requires equality_comparable<iterator_t<Base>>;
346
+ ```
347
+
348
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
349
+
350
+ ``` cpp
351
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
352
+ requires random_access_range<Base>;
353
+ ```
354
+
355
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
356
+
357
+ ``` cpp
358
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
359
+ requires random_access_range<Base>;
360
+ ```
361
+
362
+ *Effects:* Equivalent to: `return y < x;`
363
+
364
+ ``` cpp
365
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
366
+ requires random_access_range<Base>;
367
+ ```
368
+
369
+ *Effects:* Equivalent to: `return !(y < x);`
370
+
371
+ ``` cpp
372
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
373
+ requires random_access_range<Base>;
374
+ ```
375
+
376
+ *Effects:* Equivalent to: `return !(x < y);`
377
+
378
+ ``` cpp
379
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
380
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
381
+ ```
382
+
383
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
384
+
385
+ ``` cpp
386
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
387
+ requires random_access_range<Base>;
388
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
389
+ requires random_access_range<Base>;
390
+ ```
391
+
392
+ *Effects:* Equivalent to:
393
+
394
+ ``` cpp
395
+ auto r = i;
396
+ r += n;
397
+ return r;
398
+ ```
399
+
400
+ ``` cpp
401
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
402
+ requires random_access_range<Base>;
403
+ ```
404
+
405
+ *Effects:* Equivalent to:
406
+
407
+ ``` cpp
408
+ auto r = i;
409
+ r -= n;
410
+ return r;
411
+ ```
412
+
413
+ ``` cpp
414
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
415
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
416
+ ```
417
+
418
+ *Returns:* Let `N` be `(x.`*`current_`*` - y.`*`current_`*`)`.
419
+
420
+ - If *Base* models `forward_range`,
421
+ `(N + x.`*`missing_`*` - y.`*`missing_`*`) / x.`*`stride_`*.
422
+ - Otherwise, if `N` is negative, `-`*`div-ceil`*`(-N, x.`*`stride_`*`)`.
423
+ - Otherwise, *`div-ceil`*`(N, x.`*`stride_`*`)`.
424
+
425
+ ``` cpp
426
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
427
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
428
+ ```
429
+
430
+ *Returns:*
431
+ *`div-ceil`*`(x.`*`end_`*` - x.`*`current_`*`, x.`*`stride_`*`)`.
432
+
433
+ ``` cpp
434
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
435
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
436
+ ```
437
+
438
+ *Effects:* Equivalent to: `return -(y - x);`
439
+
440
+ ``` cpp
441
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
442
+ noexcept(noexcept(ranges::iter_move(i.current_)));
443
+ ```
444
+
445
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
446
+
447
+ ``` cpp
448
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
449
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
450
+ requires indirectly_swappable<iterator_t<Base>>;
451
+ ```
452
+
453
+ *Effects:* Equivalent to:
454
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`);`
455
+