From Jason Turner

[range.zip]

Diff to HTML by rtfpessoa

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