From Jason Turner

[range.concat]

Diff to HTML by rtfpessoa

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