From Jason Turner

[range.adjacent]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpkaga7out/{from.md → to.md} +489 -0
tmp/tmpkaga7out/{from.md → to.md} RENAMED
@@ -0,0 +1,489 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Adjacent view <a id="range.adjacent">[[range.adjacent]]</a>
2
+
3
+ #### Overview <a id="range.adjacent.overview">[[range.adjacent.overview]]</a>
4
+
5
+ `adjacent_view` takes a view and produces a view whose Mᵗʰ element is a
6
+ tuple of references to the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
7
+ original view. If the original view has fewer than N elements, the
8
+ resulting view is empty.
9
+
10
+ The name `views::adjacent<N>` denotes a range adaptor object
11
+ [[range.adaptor.object]]. Given a subexpression `E` and a constant
12
+ expression `N`, the expression `views::adjacent<N>(E)` is
13
+ expression-equivalent to
14
+
15
+ - `((void)E, auto(views::empty<tuple<>>))` if `N` is equal to `0`,
16
+ - otherwise, `adjacent_view<views::all_t<decltype((E))>, N>(E)`.
17
+
18
+ [*Example 1*:
19
+
20
+ ``` cpp
21
+ vector v = {1, 2, 3, 4};
22
+
23
+ for (auto i : v | views::adjacent<2>) {
24
+ cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints (1, 2) (2, 3) (3, 4)
25
+ }
26
+ ```
27
+
28
+ — *end example*]
29
+
30
+ Define `REPEAT(T, N)` as a pack of `N` types, each of which denotes the
31
+ same type as `T`.
32
+
33
+ #### Class template `adjacent_view` <a id="range.adjacent.view">[[range.adjacent.view]]</a>
34
+
35
+ ``` cpp
36
+ namespace std::ranges {
37
+ template<forward_range V, size_t N>
38
+ requires view<V> && (N > 0)
39
+ class adjacent_view : public view_interface<adjacent_view<V, N>> {
40
+ V base_ = V(); // exposition only
41
+
42
+ // [range.adjacent.iterator], class template adjacent_view::iterator
43
+ template<bool> class iterator; // exposition only
44
+
45
+ // [range.adjacent.sentinel], class template adjacent_view::sentinel
46
+ template<bool> class sentinel; // exposition only
47
+
48
+ struct as-sentinel{}; // exposition only
49
+
50
+ public:
51
+ adjacent_view() requires default_initializable<V> = default;
52
+ constexpr explicit adjacent_view(V base);
53
+
54
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
55
+ constexpr V base() && { return std::move(base_); }
56
+
57
+ constexpr auto begin() requires (!simple-view<V>) {
58
+ return iterator<false>(ranges::begin(base_), ranges::end(base_));
59
+ }
60
+
61
+ constexpr auto begin() const requires range<const V> {
62
+ return iterator<true>(ranges::begin(base_), ranges::end(base_));
63
+ }
64
+
65
+ constexpr auto end() requires (!simple-view<V>) {
66
+ if constexpr (common_range<V>) {
67
+ return iterator<false>(as-sentinel{}, ranges::begin(base_), ranges::end(base_));
68
+ } else {
69
+ return sentinel<false>(ranges::end(base_));
70
+ }
71
+ }
72
+
73
+ constexpr auto end() const requires range<const V> {
74
+ if constexpr (common_range<const V>) {
75
+ return iterator<true>(as-sentinel{}, ranges::begin(base_), ranges::end(base_));
76
+ } else {
77
+ return sentinel<true>(ranges::end(base_));
78
+ }
79
+ }
80
+
81
+ constexpr auto size() requires sized_range<V>;
82
+ constexpr auto size() const requires sized_range<const V>;
83
+ };
84
+ }
85
+ ```
86
+
87
+ ``` cpp
88
+ constexpr explicit adjacent_view(V base);
89
+ ```
90
+
91
+ *Effects:* Initializes *base\_* with `std::move(base)`.
92
+
93
+ ``` cpp
94
+ constexpr auto size() requires sized_range<V>;
95
+ constexpr auto size() const requires sized_range<const V>;
96
+ ```
97
+
98
+ *Effects:* Equivalent to:
99
+
100
+ ``` cpp
101
+ using ST = decltype(ranges::size(base_));
102
+ using CT = common_type_t<ST, size_t>;
103
+ auto sz = static_cast<CT>(ranges::size(base_));
104
+ sz -= std::min<CT>(sz, N - 1);
105
+ return static_cast<ST>(sz);
106
+ ```
107
+
108
+ #### Class template `adjacent_view::iterator` <a id="range.adjacent.iterator">[[range.adjacent.iterator]]</a>
109
+
110
+ ``` cpp
111
+ namespace std::ranges {
112
+ template<forward_range V, size_t N>
113
+ requires view<V> && (N > 0)
114
+ template<bool Const>
115
+ class adjacent_view<V, N>::iterator {
116
+ using Base = maybe-const<Const, V>; // exposition only
117
+ array<iterator_t<Base>, N> current_ = array<iterator_t<Base>, N>(); // exposition only
118
+ constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last); // exposition only
119
+ constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
120
+ // exposition only
121
+ public:
122
+ using iterator_category = input_iterator_tag;
123
+ using iterator_concept = see below;
124
+ using value_type = tuple<REPEAT(range_value_t<Base>, N)...>;
125
+ using difference_type = range_difference_t<Base>;
126
+
127
+ iterator() = default;
128
+ constexpr iterator(iterator<!Const> i)
129
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
130
+
131
+ constexpr auto operator*() const;
132
+ constexpr iterator& operator++();
133
+ constexpr iterator operator++(int);
134
+
135
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
136
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
137
+
138
+ constexpr iterator& operator+=(difference_type x)
139
+ requires random_access_range<Base>;
140
+ constexpr iterator& operator-=(difference_type x)
141
+ requires random_access_range<Base>;
142
+
143
+ constexpr auto operator[](difference_type n) const
144
+ requires random_access_range<Base>;
145
+
146
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
147
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
148
+ requires random_access_range<Base>;
149
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
150
+ requires random_access_range<Base>;
151
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
152
+ requires random_access_range<Base>;
153
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
154
+ requires random_access_range<Base>;
155
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
156
+ requires random_access_range<Base> &&
157
+ three_way_comparable<iterator_t<Base>>;
158
+
159
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
160
+ requires random_access_range<Base>;
161
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
162
+ requires random_access_range<Base>;
163
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
164
+ requires random_access_range<Base>;
165
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
166
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
167
+
168
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
169
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
170
+ requires indirectly_swappable<iterator_t<Base>>;
171
+ };
172
+ }
173
+ ```
174
+
175
+ `iterator::iterator_concept` is defined as follows:
176
+
177
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
178
+ denotes `random_access_iterator_tag`.
179
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
180
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
181
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
182
+
183
+ If the invocation of any non-const member function of *`iterator`* exits
184
+ via an exception, the *`iterator`* acquires a singular value.
185
+
186
+ ``` cpp
187
+ constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last);
188
+ ```
189
+
190
+ *Ensures:* *`current_`*`[0] == first` is `true`, and for every integer
191
+ 1 ≤ i < `N`,
192
+ *`current_`*`[`i`] == ranges::next(`*`current_`*`[`i`-1], 1, last)` is
193
+ `true`.
194
+
195
+ ``` cpp
196
+ constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
197
+ ```
198
+
199
+ *Ensures:* If *Base* does not model `bidirectional_range`, each element
200
+ of *current\_* is equal to *last*. Otherwise,
201
+ *`current_`*`[N-1] == last` is `true`, and for every integer
202
+ 0 ≤ i < (`N` - 1),
203
+ *`current_`*`[`i`] == ranges::prev(`*`current_`*`[`i`+1], 1, first)` is
204
+ `true`.
205
+
206
+ ``` cpp
207
+ constexpr iterator(iterator<!Const> i)
208
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
209
+ ```
210
+
211
+ *Effects:* Initializes each element of *current\_* with the
212
+ corresponding element of `i.`*`current_`* as an xvalue.
213
+
214
+ ``` cpp
215
+ constexpr auto operator*() const;
216
+ ```
217
+
218
+ *Effects:* Equivalent to:
219
+
220
+ ``` cpp
221
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
222
+ ```
223
+
224
+ ``` cpp
225
+ constexpr iterator& operator++();
226
+ ```
227
+
228
+ *Preconditions:* *`current_`*`.back()` is incrementable.
229
+
230
+ *Ensures:* Each element of *current\_* is equal to `ranges::next(i)`,
231
+ where `i` is the value of that element before the call.
232
+
233
+ *Returns:* `*this`.
234
+
235
+ ``` cpp
236
+ constexpr iterator operator++(int);
237
+ ```
238
+
239
+ *Effects:* Equivalent to:
240
+
241
+ ``` cpp
242
+ auto tmp = *this;
243
+ ++*this;
244
+ return tmp;
245
+ ```
246
+
247
+ ``` cpp
248
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
249
+ ```
250
+
251
+ *Preconditions:* *`current_`*`.front()` is decrementable.
252
+
253
+ *Ensures:* Each element of *current\_* is equal to `ranges::prev(i)`,
254
+ where `i` is the value of that element before the call.
255
+
256
+ *Returns:* `*this`.
257
+
258
+ ``` cpp
259
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
260
+ ```
261
+
262
+ *Effects:* Equivalent to:
263
+
264
+ ``` cpp
265
+ auto tmp = *this;
266
+ --*this;
267
+ return tmp;
268
+ ```
269
+
270
+ ``` cpp
271
+ constexpr iterator& operator+=(difference_type x)
272
+ requires random_access_range<Base>;
273
+ ```
274
+
275
+ *Preconditions:* *`current_`*`.back() + x` has well-defined behavior.
276
+
277
+ *Ensures:* Each element of *current\_* is equal to `i + x`, where `i` is
278
+ the value of that element before the call.
279
+
280
+ *Returns:* `*this`.
281
+
282
+ ``` cpp
283
+ constexpr iterator& operator-=(difference_type x)
284
+ requires random_access_range<Base>;
285
+ ```
286
+
287
+ *Preconditions:* *`current_`*`.front() - x` has well-defined behavior.
288
+
289
+ *Ensures:* Each element of *current\_* is equal to `i - x`, where `i` is
290
+ the value of that element before the call.
291
+
292
+ *Returns:* `*this`.
293
+
294
+ ``` cpp
295
+ constexpr auto operator[](difference_type n) const
296
+ requires random_access_range<Base>;
297
+ ```
298
+
299
+ *Effects:* Equivalent to:
300
+
301
+ ``` cpp
302
+ return tuple-transform([&](auto& i) -> decltype(auto) { return i[n]; }, current_);
303
+ ```
304
+
305
+ ``` cpp
306
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
307
+ ```
308
+
309
+ *Returns:* `x.`*`current_`*`.back() == y.`*`current_`*`.back()`.
310
+
311
+ ``` cpp
312
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
313
+ requires random_access_range<Base>;
314
+ ```
315
+
316
+ *Returns:* `x.`*`current_`*`.back() < y.`*`current_`*`.back()`.
317
+
318
+ ``` cpp
319
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
320
+ requires random_access_range<Base>;
321
+ ```
322
+
323
+ *Effects:* Equivalent to: `return y < x;`
324
+
325
+ ``` cpp
326
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
327
+ requires random_access_range<Base>;
328
+ ```
329
+
330
+ *Effects:* Equivalent to: `return !(y < x);`
331
+
332
+ ``` cpp
333
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
334
+ requires random_access_range<Base>;
335
+ ```
336
+
337
+ *Effects:* Equivalent to: `return !(x < y);`
338
+
339
+ ``` cpp
340
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
341
+ requires random_access_range<Base> &&
342
+ three_way_comparable<iterator_t<Base>>;
343
+ ```
344
+
345
+ *Returns:* `x.`*`current_`*`.back() <=> y.`*`current_`*`.back()`.
346
+
347
+ ``` cpp
348
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
349
+ requires random_access_range<Base>;
350
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
351
+ requires random_access_range<Base>;
352
+ ```
353
+
354
+ *Effects:* Equivalent to:
355
+
356
+ ``` cpp
357
+ auto r = i;
358
+ r += n;
359
+ return r;
360
+ ```
361
+
362
+ ``` cpp
363
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
364
+ requires random_access_range<Base>;
365
+ ```
366
+
367
+ *Effects:* Equivalent to:
368
+
369
+ ``` cpp
370
+ auto r = i;
371
+ r -= n;
372
+ return r;
373
+ ```
374
+
375
+ ``` cpp
376
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
377
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
378
+ ```
379
+
380
+ *Effects:* Equivalent to:
381
+ `return x.`*`current_`*`.back() - y.`*`current_`*`.back();`
382
+
383
+ ``` cpp
384
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
385
+ ```
386
+
387
+ *Effects:* Equivalent to:
388
+ `return `*`tuple-transform`*`(ranges::iter_move, i.`*`current_`*`);`
389
+
390
+ *Remarks:* The exception specification is equivalent to:
391
+
392
+ ``` cpp
393
+ noexcept(ranges::iter_move(declval<const iterator_t<Base>&>())) &&
394
+ is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>
395
+ ```
396
+
397
+ ``` cpp
398
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
399
+ requires indirectly_swappable<iterator_t<Base>>;
400
+ ```
401
+
402
+ *Preconditions:* None of the iterators in `l.`*`current_`* is equal to
403
+ an iterator in `r.`*`current_`*.
404
+
405
+ *Effects:* For every integer 0 ≤ i < `N`, performs
406
+ `ranges::iter_swap(l.`*`current_`*`[`i`], r.`*`current_`*`[`i`])`.
407
+
408
+ *Remarks:* The exception specification is equivalent to:
409
+
410
+ ``` cpp
411
+ noexcept(ranges::iter_swap(declval<iterator_t<Base>>(), declval<iterator_t<Base>>()))
412
+ ```
413
+
414
+ #### Class template `adjacent_view::sentinel` <a id="range.adjacent.sentinel">[[range.adjacent.sentinel]]</a>
415
+
416
+ ``` cpp
417
+ namespace std::ranges {
418
+ template<forward_range V, size_t N>
419
+ requires view<V> && (N > 0)
420
+ template<bool Const>
421
+ class adjacent_view<V, N>::sentinel {
422
+ using Base = maybe-const<Const, V>; // exposition only
423
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
424
+ constexpr explicit sentinel(sentinel_t<Base> end); // exposition only
425
+
426
+ public:
427
+ sentinel() = default;
428
+ constexpr sentinel(sentinel<!Const> i)
429
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
430
+
431
+ template<bool OtherConst>
432
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
433
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
434
+
435
+ template<bool OtherConst>
436
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
437
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
438
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
439
+
440
+ template<bool OtherConst>
441
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
442
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
443
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
444
+ };
445
+ }
446
+ ```
447
+
448
+ ``` cpp
449
+ constexpr explicit sentinel(sentinel_t<Base> end);
450
+ ```
451
+
452
+ *Effects:* Initializes *end\_* with `end`.
453
+
454
+ ``` cpp
455
+ constexpr sentinel(sentinel<!Const> i)
456
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
457
+ ```
458
+
459
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
460
+
461
+ ``` cpp
462
+ template<bool OtherConst>
463
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
464
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
465
+ ```
466
+
467
+ *Effects:* Equivalent to:
468
+ `return x.`*`current_`*`.back() == y.`*`end_`*`;`
469
+
470
+ ``` cpp
471
+ template<bool OtherConst>
472
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
473
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
474
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
475
+ ```
476
+
477
+ *Effects:* Equivalent to:
478
+ `return x.`*`current_`*`.back() - y.`*`end_`*`;`
479
+
480
+ ``` cpp
481
+ template<bool OtherConst>
482
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
483
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
484
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
485
+ ```
486
+
487
+ *Effects:* Equivalent to:
488
+ `return y.`*`end_`*` - x.`*`current_`*`.back();`
489
+