From Jason Turner

[ranges]

Large diff (428.5 KB) - rendering may be slow on some devices

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpwzgs6c7r/{from.md → to.md} +8501 -942
tmp/tmpwzgs6c7r/{from.md → to.md} RENAMED
@@ -1,23 +1,25 @@
1
  # Ranges library <a id="ranges">[[ranges]]</a>
2
 
3
  ## General <a id="ranges.general">[[ranges.general]]</a>
4
 
5
- This clause describes components for dealing with ranges of elements.
6
 
7
  The following subclauses describe range and view requirements, and
8
- components for range primitives as summarized in [[range.summary]].
 
9
 
10
  **Table: Ranges library summary** <a id="range.summary">[range.summary]</a>
11
 
12
  | Subclause | | Header |
13
- | ------------------- | --------------- | ---------- |
14
  | [[range.access]] | Range access | `<ranges>` |
15
  | [[range.req]] | Requirements | |
16
  | [[range.utility]] | Range utilities | |
17
  | [[range.factories]] | Range factories | |
18
  | [[range.adaptors]] | Range adaptors | |
 
19
 
20
 
21
  ## Header `<ranges>` synopsis <a id="ranges.syn">[[ranges.syn]]</a>
22
 
23
  ``` cpp
@@ -26,306 +28,569 @@ components for range primitives as summarized in [[range.summary]].
26
  #include <iterator> // see [iterator.synopsis]
27
 
28
  namespace std::ranges {
29
  inline namespace unspecified {
30
  // [range.access], range access
31
- inline constexpr unspecified begin = unspecified;
32
- inline constexpr unspecified end = unspecified;
33
- inline constexpr unspecified cbegin = unspecified;
34
- inline constexpr unspecified cend = unspecified;
35
- inline constexpr unspecified rbegin = unspecified;
36
- inline constexpr unspecified rend = unspecified;
37
- inline constexpr unspecified crbegin = unspecified;
38
- inline constexpr unspecified crend = unspecified;
39
 
40
- inline constexpr unspecified size = unspecified;
41
- inline constexpr unspecified ssize = unspecified;
42
- inline constexpr unspecified empty = unspecified;
43
- inline constexpr unspecified data = unspecified;
44
- inline constexpr unspecified cdata = unspecified;
45
  }
46
 
47
  // [range.range], ranges
48
  template<class T>
49
- concept range = see below;
50
 
51
  template<class T>
52
- inline constexpr bool enable_borrowed_range = false;
53
 
54
  template<class T>
55
- concept borrowed_range = see below;
56
 
57
  template<class T>
58
- using iterator_t = decltype(ranges::begin(declval<T&>()));
59
  template<range R>
60
- using sentinel_t = decltype(ranges::end(declval<R&>()));
61
  template<range R>
62
- using range_difference_t = iter_difference_t<iterator_t<R>>;
 
 
 
 
63
  template<sized_range R>
64
- using range_size_t = decltype(ranges::size(declval<R&>()));
65
  template<range R>
66
- using range_value_t = iter_value_t<iterator_t<R>>;
67
  template<range R>
68
- using range_reference_t = iter_reference_t<iterator_t<R>>;
69
  template<range R>
70
- using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
 
 
 
 
71
 
72
  // [range.sized], sized ranges
73
  template<class>
74
- inline constexpr bool disable_sized_range = false;
75
 
76
  template<class T>
77
- concept sized_range = see below;
78
 
79
  // [range.view], views
80
  template<class T>
81
- inline constexpr bool enable_view = see below;
82
 
83
- struct view_base { };
84
 
85
  template<class T>
86
- concept view = see below;
87
 
88
  // [range.refinements], other range refinements
89
  template<class R, class T>
90
- concept output_range = see below;
91
 
92
  template<class T>
93
- concept input_range = see below;
94
 
95
  template<class T>
96
- concept forward_range = see below;
97
 
98
  template<class T>
99
- concept bidirectional_range = see below;
100
 
101
  template<class T>
102
- concept random_access_range = see below;
103
 
104
  template<class T>
105
- concept contiguous_range = see below;
106
 
107
  template<class T>
108
- concept common_range = see below;
109
 
110
  template<class T>
111
- concept viewable_range = see below;
 
 
 
112
 
113
  // [view.interface], class template view_interface
114
  template<class D>
115
  requires is_class_v<D> && same_as<D, remove_cv_t<D>>
116
- class view_interface;
117
 
118
  // [range.subrange], sub-ranges
119
- enum class subrange_kind : bool { unsized, sized };
120
 
121
  template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K = see below>
122
  requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
123
- class subrange;
124
 
125
- template<input_or_output_iterator I, sentinel_for<I> S, subrange_kind K>
126
- inline constexpr bool enable_borrowed_range<subrange<I, S, K>> = true;
127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  // [range.dangling], dangling iterator handling
129
- struct dangling;
 
 
 
 
130
 
131
  template<range R>
132
- using borrowed_iterator_t = conditional_t<borrowed_range<R>, iterator_t<R>, dangling>;
133
 
134
  template<range R>
135
- using borrowed_subrange_t =
136
- conditional_t<borrowed_range<R>, subrange<iterator_t<R>>, dangling>;
 
 
 
 
 
 
 
 
 
137
 
138
  // [range.empty], empty view
139
  template<class T>
140
  requires is_object_v<T>
141
- class empty_view;
142
 
143
  template<class T>
144
- inline constexpr bool enable_borrowed_range<empty_view<T>> = true;
145
 
146
  namespace views {
147
  template<class T>
148
- inline constexpr empty_view<T> empty{};
149
  }
150
 
151
  // [range.single], single view
152
- template<copy_constructible T>
153
  requires is_object_v<T>
154
- class single_view;
155
 
156
- namespace views { inline constexpr unspecified single = unspecified; }
 
 
 
157
 
158
  // [range.iota], iota view
159
  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
160
- requires weakly-equality-comparable-with<W, Bound>
161
- class iota_view;
162
 
163
- template<weakly_incrementable W, semiregular Bound>
164
- inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
165
 
166
- namespace views { inline constexpr unspecified iota = unspecified; }
 
 
 
 
 
 
 
167
 
168
  // [range.istream], istream view
169
  template<movable Val, class CharT, class Traits = char_traits<CharT>>
170
  requires see below
171
  class basic_istream_view;
172
- template<class Val, class CharT, class Traits>
173
- basic_istream_view<Val, CharT, Traits> istream_view(basic_istream<CharT, Traits>& s);
 
 
 
 
 
 
 
 
 
174
 
175
  // [range.all], all view
176
  namespace views {
177
- inline constexpr unspecified all = unspecified;
178
 
179
  template<viewable_range R>
180
- using all_t = decltype(all(declval<R>()));
181
  }
182
 
 
183
  template<range R>
184
  requires is_object_v<R>
185
- class ref_view;
186
 
187
  template<class T>
188
- inline constexpr bool enable_borrowed_range<ref_view<T>> = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
 
190
  // [range.filter], filter view
191
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
192
  requires view<V> && is_object_v<Pred>
193
- class filter_view;
194
 
195
- namespace views { inline constexpr unspecified filter = unspecified; }
196
 
197
  // [range.transform], transform view
198
- template<input_range V, copy_constructible F>
199
  requires view<V> && is_object_v<F> &&
200
- regular_invocable<F&, range_reference_t<V>>
201
- class transform_view;
 
202
 
203
- namespace views { inline constexpr unspecified transform = unspecified; }
204
 
205
  // [range.take], take view
206
- template<view> class take_view;
207
 
208
- namespace views { inline constexpr unspecified take = unspecified; }
 
 
 
 
209
 
210
  // [range.take.while], take while view
211
  template<view V, class Pred>
212
  requires input_range<V> && is_object_v<Pred> &&
213
  indirect_unary_predicate<const Pred, iterator_t<V>>
214
- class take_while_view;
215
 
216
- namespace views { inline constexpr unspecified take_while = unspecified; }
217
 
218
  // [range.drop], drop view
219
  template<view V>
220
- class drop_view;
221
 
222
- namespace views { inline constexpr unspecified drop = unspecified; }
 
 
 
 
223
 
224
  // [range.drop.while], drop while view
225
  template<view V, class Pred>
226
  requires input_range<V> && is_object_v<Pred> &&
227
  indirect_unary_predicate<const Pred, iterator_t<V>>
228
- class drop_while_view;
229
 
230
- namespace views { inline constexpr unspecified drop_while = unspecified; }
 
 
 
 
231
 
232
  // [range.join], join view
233
  template<input_range V>
234
- requires view<V> && input_range<range_reference_t<V>> &&
235
- (is_reference_v<range_reference_t<V>> ||
236
- view<range_value_t<V>>)
237
- class join_view;
238
 
239
- namespace views { inline constexpr unspecified join = unspecified; }
240
 
241
- // [range.split], split view
 
 
 
 
 
 
 
 
 
 
 
 
242
  template<class R>
243
  concept tiny-range = see below; // exposition only
244
 
245
  template<input_range V, forward_range Pattern>
246
  requires view<V> && view<Pattern> &&
247
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
248
  (forward_range<V> || tiny-range<Pattern>)
249
- class split_view;
250
 
251
- namespace views { inline constexpr unspecified split = unspecified; }
 
 
 
 
 
 
 
 
 
252
 
253
  // [range.counted], counted view
254
- namespace views { inline constexpr unspecified counted = unspecified; }
255
 
256
  // [range.common], common view
257
  template<view V>
258
  requires (!common_range<V> && copyable<iterator_t<V>>)
259
- class common_view;
260
 
261
- namespace views { inline constexpr unspecified common = unspecified; }
 
 
 
 
262
 
263
  // [range.reverse], reverse view
264
  template<view V>
265
  requires bidirectional_range<V>
266
- class reverse_view;
267
 
268
- namespace views { inline constexpr unspecified reverse = unspecified; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  // [range.elements], elements view
271
  template<input_range V, size_t N>
272
- requires see below;
273
- class elements_view;
 
 
 
 
274
 
275
  template<class R>
276
- using keys_view = elements_view<views::all_t<R>, 0>;
277
  template<class R>
278
- using values_view = elements_view<views::all_t<R>, 1>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
 
280
  namespace views {
281
  template<size_t N>
282
- inline constexpr unspecified elements = unspecified ;
283
- inline constexpr auto keys = elements<0>;
284
- inline constexpr auto values = elements<1>;
285
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  }
287
 
288
  namespace std {
289
- namespace views = ranges::views;
 
 
 
290
 
291
  template<class I, class S, ranges::subrange_kind K>
292
- struct tuple_size<ranges::subrange<I, S, K>>
293
  : integral_constant<size_t, 2> {};
294
  template<class I, class S, ranges::subrange_kind K>
295
- struct tuple_element<0, ranges::subrange<I, S, K>> {
296
- using type = I;
297
  };
298
  template<class I, class S, ranges::subrange_kind K>
299
- struct tuple_element<1, ranges::subrange<I, S, K>> {
300
- using type = S;
301
  };
302
  template<class I, class S, ranges::subrange_kind K>
303
- struct tuple_element<0, const ranges::subrange<I, S, K>> {
304
- using type = I;
305
  };
306
  template<class I, class S, ranges::subrange_kind K>
307
- struct tuple_element<1, const ranges::subrange<I, S, K>> {
308
- using type = S;
309
  };
 
 
 
310
  }
311
  ```
312
 
313
- Within this clause, for an integer-like type `X`
314
  [[iterator.concept.winc]], `make-unsigned-like-t<X>` denotes
315
  `make_unsigned_t<X>` if `X` is an integer type; otherwise, it denotes a
316
  corresponding unspecified unsigned-integer-like type of the same width
317
  as `X`. For an expression `x` of type `X`, `to-unsigned-like(x)` is `x`
318
  explicitly converted to `make-unsigned-like-t<X>`.
319
 
 
 
 
 
 
320
  ## Range access <a id="range.access">[[range.access]]</a>
321
 
 
 
322
  In addition to being available via inclusion of the `<ranges>` header,
323
  the customization point objects in [[range.access]] are available when
324
  `<iterator>` is included.
325
 
326
- Within this subclause, the *reified object* of a subexpression `E`
327
  denotes
328
 
329
  - the same object as `E` if `E` is a glvalue, or
330
  - the result of applying the temporary materialization conversion
331
  [[conv.rval]] to `E` otherwise.
@@ -338,31 +603,23 @@ The name `ranges::begin` denotes a customization point object
338
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
339
  denotes the reified object for `E`. Then:
340
 
341
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
342
  `false`, `ranges::begin(E)` is ill-formed.
343
- - Otherwise, if `T` is an array type [[basic.compound]] and
344
  `remove_all_extents_t<T>` is an incomplete type, `ranges::begin(E)` is
345
  ill-formed with no diagnostic required.
346
  - Otherwise, if `T` is an array type, `ranges::begin(E)` is
347
  expression-equivalent to `t + 0`.
348
- - Otherwise, if `decay-copy(t.begin())` is a valid expression whose type
349
  models `input_or_output_iterator`, `ranges::begin(E)` is
350
- expression-equivalent to `decay-copy(t.begin())`.
351
- - Otherwise, if `T` is a class or enumeration type and
352
- `decay-copy(begin(t))` is a valid expression whose type models
353
- `input_or_output_iterator` with overload resolution performed in a
354
- context in which unqualified lookup for `begin` finds only the
355
- declarations
356
- ``` cpp
357
- void begin(auto&) = delete;
358
- void begin(const auto&) = delete;
359
- ```
360
-
361
- then `ranges::begin(E)` is expression-equivalent to
362
- `decay-copy(begin(t))` with overload resolution performed in the above
363
- context.
364
  - Otherwise, `ranges::begin(E)` is ill-formed.
365
 
366
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
367
  failure when `ranges::begin(E)` appears in the immediate context of a
368
  template instantiation. — *end note*]
@@ -378,32 +635,25 @@ The name `ranges::end` denotes a customization point object
378
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
379
  denotes the reified object for `E`. Then:
380
 
381
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
382
  `false`, `ranges::end(E)` is ill-formed.
383
- - Otherwise, if `T` is an array type [[basic.compound]] and
384
  `remove_all_extents_t<T>` is an incomplete type, `ranges::end(E)` is
385
  ill-formed with no diagnostic required.
386
  - Otherwise, if `T` is an array of unknown bound, `ranges::end(E)` is
387
  ill-formed.
388
  - Otherwise, if `T` is an array, `ranges::end(E)` is
389
  expression-equivalent to `t + extent_v<T>`.
390
- - Otherwise, if `decay-copy(t.end())` is a valid expression whose type
391
- models `sentinel_for<iterator_t<T>>` then `ranges::end(E)` is
392
- expression-equivalent to `decay-copy(t.end())`.
393
- - Otherwise, if `T` is a class or enumeration type and
394
- `decay-copy(end(t))` is a valid expression whose type models
395
- `sentinel_for<iterator_t<T>>` with overload resolution performed in a
396
- context in which unqualified lookup for `end` finds only the
397
- declarations
398
- ``` cpp
399
- void end(auto&) = delete;
400
- void end(const auto&) = delete;
401
- ```
402
-
403
- then `ranges::end(E)` is expression-equivalent to `decay-copy(end(t))`
404
- with overload resolution performed in the above context.
405
  - Otherwise, `ranges::end(E)` is ill-formed.
406
 
407
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
408
  failure when `ranges::end(E)` appears in the immediate context of a
409
  template instantiation. — *end note*]
@@ -413,31 +663,39 @@ template instantiation. — *end note*]
413
  `sentinel_for<S, I>`. — *end note*]
414
 
415
  ### `ranges::cbegin` <a id="range.access.cbegin">[[range.access.cbegin]]</a>
416
 
417
  The name `ranges::cbegin` denotes a customization point object
418
- [[customization.point.object]]. The expression `ranges::{}cbegin(E)` for
419
- a subexpression `E` of type `T` is expression-equivalent to:
420
 
421
- - `ranges::begin(static_cast<const T&>(E))` if `E` is an lvalue.
422
- - Otherwise, `ranges::begin(static_cast<const T&&>(E))`.
 
 
 
423
 
424
  [*Note 1*: Whenever `ranges::cbegin(E)` is a valid expression, its type
425
- models `input_or_output_iterator`. — *end note*]
 
426
 
427
  ### `ranges::cend` <a id="range.access.cend">[[range.access.cend]]</a>
428
 
429
  The name `ranges::cend` denotes a customization point object
430
- [[customization.point.object]]. The expression `ranges::cend(E)` for a
431
- subexpression `E` of type `T` is expression-equivalent to:
432
 
433
- - `ranges::end(static_cast<const T&>(E))` if `E` is an lvalue.
434
- - Otherwise, `ranges::end(static_cast<const T&&>(E))`.
 
 
 
435
 
436
  [*Note 1*: Whenever `ranges::cend(E)` is a valid expression, the types
437
- `S` and `I` of `ranges::cend(E)` and `ranges::cbegin(E)` model
438
- `sentinel_for<S, I>`. *end note*]
 
439
 
440
  ### `ranges::rbegin` <a id="range.access.rbegin">[[range.access.rbegin]]</a>
441
 
442
  The name `ranges::rbegin` denotes a customization point object
443
  [[customization.point.object]].
@@ -445,29 +703,21 @@ The name `ranges::rbegin` denotes a customization point object
445
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
446
  denotes the reified object for `E`. Then:
447
 
448
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
449
  `false`, `ranges::rbegin(E)` is ill-formed.
450
- - Otherwise, if `T` is an array type [[basic.compound]] and
451
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rbegin(E)`
452
  is ill-formed with no diagnostic required.
453
- - Otherwise, if `decay-copy(t.rbegin())` is a valid expression whose
454
- type models `input_or_output_iterator`, `ranges::rbegin(E)` is
455
- expression-equivalent to `decay-copy(t.rbegin())`.
456
- - Otherwise, if `T` is a class or enumeration type and
457
- `decay-copy(rbegin(t))` is a valid expression whose type models
458
- `input_or_output_iterator` with overload resolution performed in a
459
- context in which unqualified lookup for `rbegin` finds only the
460
- declarations
461
- ``` cpp
462
- void rbegin(auto&) = delete;
463
- void rbegin(const auto&) = delete;
464
- ```
465
-
466
- then `ranges::rbegin(E)` is expression-equivalent to
467
- `decay-copy(rbegin(t))` with overload resolution performed in the
468
- above context.
469
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
470
  expressions of the same type which models `bidirectional_iterator`
471
  [[iterator.concept.bidir]], `ranges::rbegin(E)` is
472
  expression-equivalent to `make_reverse_iterator(ranges::end(t))`.
473
  - Otherwise, `ranges::rbegin(E)` is ill-formed.
@@ -487,30 +737,22 @@ The name `ranges::rend` denotes a customization point object
487
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
488
  denotes the reified object for `E`. Then:
489
 
490
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
491
  `false`, `ranges::rend(E)` is ill-formed.
492
- - Otherwise, if `T` is an array type [[basic.compound]] and
493
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rend(E)` is
494
  ill-formed with no diagnostic required.
495
- - Otherwise, if `decay-copy(t.rend())` is a valid expression whose type
496
- models `sentinel_for<decltype(ranges::rbegin(E))>` then
497
- `ranges::rend(E)` is expression-equivalent to
498
- `decay-copy(t.rend({}))`.
499
- - Otherwise, if `T` is a class or enumeration type and
500
- `decay-copy(rend(t))` is a valid expression whose type models
501
- `sentinel_for<decltype(ranges::rbegin(E))>` with overload resolution
502
- performed in a context in which unqualified lookup for `rend` finds
503
- only the declarations
504
- ``` cpp
505
- void rend(auto&) = delete;
506
- void rend(const auto&) = delete;
507
- ```
508
-
509
- then `ranges::rend(E)` is expression-equivalent to
510
- `decay-copy(rend(t))` with overload resolution performed in the above
511
- context.
512
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
513
  expressions of the same type which models `bidirectional_iterator`
514
  [[iterator.concept.bidir]], then `ranges::rend(E)` is
515
  expression-equivalent to `make_reverse_iterator(ranges::begin(t))`.
516
  - Otherwise, `ranges::rend(E)` is ill-formed.
@@ -518,67 +760,69 @@ denotes the reified object for `E`. Then:
518
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
519
  failure when `ranges::rend(E)` appears in the immediate context of a
520
  template instantiation. — *end note*]
521
 
522
  [*Note 2*: Whenever `ranges::rend(E)` is a valid expression, the types
523
- `S` and `I` of `ranges::rend(E)` and `ranges::rbegin(E)` model
524
- `sentinel_for<S, I>`. — *end note*]
525
 
526
  ### `ranges::crbegin` <a id="range.access.crbegin">[[range.access.crbegin]]</a>
527
 
528
  The name `ranges::crbegin` denotes a customization point object
529
- [[customization.point.object]]. The expression `ranges::{}crbegin(E)`
530
- for a subexpression `E` of type `T` is expression-equivalent to:
531
 
532
- - `ranges::{}rbegin(static_cast<const T&>(E))` if `E` is an lvalue.
533
- - Otherwise, `ranges::rbegin(static_cast<const T&&>(E))`.
 
 
 
534
 
535
  [*Note 1*: Whenever `ranges::crbegin(E)` is a valid expression, its
536
- type models `input_or_output_iterator`. — *end note*]
 
537
 
538
  ### `ranges::crend` <a id="range.access.crend">[[range.access.crend]]</a>
539
 
540
  The name `ranges::crend` denotes a customization point object
541
- [[customization.point.object]]. The expression `ranges::{}crend(E)` for
542
- a subexpression `E` of type `T` is expression-equivalent to:
543
 
544
- - `ranges::rend(static_cast<const T&>(E))` if `E` is an lvalue.
545
- - Otherwise, `ranges::rend(static_cast<const T&&>(E))`.
 
 
 
546
 
547
  [*Note 1*: Whenever `ranges::crend(E)` is a valid expression, the types
548
- `S` and `I` of `ranges::crend(E)` and `ranges::crbegin(E)` model
549
- `sentinel_for<S, I>`. *end note*]
 
 
550
 
551
  ### `ranges::size` <a id="range.prim.size">[[range.prim.size]]</a>
552
 
553
  The name `ranges::size` denotes a customization point object
554
  [[customization.point.object]].
555
 
556
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
557
  denotes the reified object for `E`. Then:
558
 
559
- - If `T` is an array of unknown bound [[dcl.array]], `ranges::size(E)`
560
- is ill-formed.
561
  - Otherwise, if `T` is an array type, `ranges::size(E)` is
562
- expression-equivalent to `decay-copy(extent_v<T>)`.
563
  - Otherwise, if `disable_sized_range<remove_cv_t<T>>` [[range.sized]] is
564
- `false` and `decay-copy(t.size())` is a valid expression of
565
- integer-like type [[iterator.concept.winc]], `ranges::size(E)` is
566
- expression-equivalent to `decay-copy(t.size())`.
567
  - Otherwise, if `T` is a class or enumeration type,
568
- `disable_sized_range<remove_cv_t<T>>` is `false` and
569
- `decay-copy(size(t))` is a valid expression of integer-like type with
570
- overload resolution performed in a context in which unqualified lookup
571
- for `size` finds only the declarations
572
- ``` cpp
573
- void size(auto&) = delete;
574
- void size(const auto&) = delete;
575
- ```
576
-
577
- then `ranges::size(E)` is expression-equivalent to
578
- `decay-copy(size(t))` with overload resolution performed in the above
579
- context.
580
  - Otherwise, if `to-unsigned-like(ranges::end(t) - ranges::begin(t))`
581
  [[ranges.syn]] is a valid expression and the types `I` and `S` of
582
  `ranges::begin(t)` and `ranges::end(t)` (respectively) model both
583
  `sized_sentinel_for<S, I>` [[iterator.concept.sizedsentinel]] and
584
  `forward_iterator<I>`, then `ranges::size(E)` is expression-equivalent
@@ -593,26 +837,28 @@ template instantiation. — *end note*]
593
  is integer-like. — *end note*]
594
 
595
  ### `ranges::ssize` <a id="range.prim.ssize">[[range.prim.ssize]]</a>
596
 
597
  The name `ranges::ssize` denotes a customization point object
598
- [[customization.point.object]]. The expression `ranges::ssize({}E)` for
599
- a subexpression `E` of type `T` is expression-equivalent to:
600
 
601
- - If `range_difference_t<T>` has width less than `ptrdiff_t`,
602
- `static_cast<ptrdiff_t>(ranges::{}size(E))`.
603
- - Otherwise, `static_cast<range_difference_t<T>>(ranges::size(E))`.
 
 
 
604
 
605
  ### `ranges::empty` <a id="range.prim.empty">[[range.prim.empty]]</a>
606
 
607
  The name `ranges::empty` denotes a customization point object
608
  [[customization.point.object]].
609
 
610
- Given a subexpression `ranges::empty(E)` with type `T`, let `t` be an
611
- lvalue that denotes the reified object for `E`. Then:
612
 
613
- - If `T` is an array of unknown bound [[basic.compound]],
614
  `ranges::empty(E)` is ill-formed.
615
  - Otherwise, if `bool(t.empty())` is a valid expression,
616
  `ranges::empty(E)` is expression-equivalent to `bool(t.empty())`.
617
  - Otherwise, if `(ranges::size(t) == 0)` is a valid expression,
618
  `ranges::empty(E)` is expression-equivalent to
@@ -638,19 +884,19 @@ The name `ranges::data` denotes a customization point object
638
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
639
  denotes the reified object for `E`. Then:
640
 
641
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
642
  `false`, `ranges::data(E)` is ill-formed.
643
- - Otherwise, if `T` is an array type [[basic.compound]] and
644
  `remove_all_extents_t<T>` is an incomplete type, `ranges::data(E)` is
645
  ill-formed with no diagnostic required.
646
- - Otherwise, if `decay-copy(t.data())` is a valid expression of pointer
647
- to object type, `ranges::data(E)` is expression-equivalent to
648
- `decay-copy(t.data())`.
649
  - Otherwise, if `ranges::begin(t)` is a valid expression whose type
650
  models `contiguous_iterator`, `ranges::data(E)` is
651
- expression-equivalent to `to_address(ranges::begin(E))`.
652
  - Otherwise, `ranges::data(E)` is ill-formed.
653
 
654
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
655
  failure when `ranges::data(E)` appears in the immediate context of a
656
  template instantiation. — *end note*]
@@ -658,25 +904,32 @@ template instantiation. — *end note*]
658
  [*Note 2*: Whenever `ranges::data(E)` is a valid expression, it has
659
  pointer to object type. — *end note*]
660
 
661
  ### `ranges::cdata` <a id="range.prim.cdata">[[range.prim.cdata]]</a>
662
 
 
 
 
 
 
663
  The name `ranges::cdata` denotes a customization point object
664
- [[customization.point.object]]. The expression `ranges::{}cdata(E)` for
665
- a subexpression `E` of type `T` is expression-equivalent to:
666
 
667
- - `ranges::data(static_cast<const T&>(E))` if `E` is an lvalue.
668
- - Otherwise, `ranges::data(static_cast<const T&&>(E))`.
 
 
669
 
670
  [*Note 1*: Whenever `ranges::cdata(E)` is a valid expression, it has
671
- pointer to object type. — *end note*]
672
 
673
  ## Range requirements <a id="range.req">[[range.req]]</a>
674
 
675
  ### General <a id="range.req.general">[[range.req.general]]</a>
676
 
677
- Ranges are an abstraction that allow a C++ program to operate on
678
  elements of data structures uniformly. Calling `ranges::begin` on a
679
  range returns an object whose type models `input_or_output_iterator`
680
  [[iterator.concept.iterator]]. Calling `ranges::end` on a range returns
681
  an object whose type `S`, together with the type `I` of the object
682
  returned by `ranges::begin`, models `sentinel_for<S, I>`. The library
@@ -686,11 +939,11 @@ of sequences.
686
 
687
  The `range` concept requires that `ranges::begin` and `ranges::end`
688
  return an iterator and a sentinel, respectively. The `sized_range`
689
  concept refines `range` with the requirement that `ranges::size` be
690
  amortized 𝑂(1). The `view` concept specifies requirements on a `range`
691
- type with constant-time destruction and move operations.
692
 
693
  Several refinements of `range` group requirements that arise frequently
694
  in concepts and algorithms. Common ranges are ranges for which
695
  `ranges::begin` and `ranges::end` return objects of the same type.
696
  Random access ranges are ranges for which `ranges::begin` returns a type
@@ -726,37 +979,37 @@ Given an expression `t` such that `decltype((t))` is `T&`, `T` models
726
  time and non-modifying, and
727
  - if the type of `ranges::begin(t)` models `forward_iterator`,
728
  `ranges::begin(t)` is equality-preserving.
729
 
730
  [*Note 1*: Equality preservation of both `ranges::begin` and
731
- `ranges::end` enables passing a `range` whose iterator type models
732
  `forward_iterator` to multiple algorithms and making multiple passes
733
  over the range by repeated calls to `ranges::begin` and `ranges::end`.
734
  Since `ranges::begin` is not required to be equality-preserving when the
735
- return type does not model `forward_iterator`, repeated calls might not
736
- return equal values or might not be well-defined; `ranges::begin` should
737
- be called at most once for such a range. — *end note*]
738
 
739
  ``` cpp
740
  template<class T>
741
  concept borrowed_range =
742
- range<T> &&
743
- (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
744
  ```
745
 
746
- Given an expression `E` such that `decltype((E))` is `T`, `T` models
747
- `borrowed_range` only if the validity of iterators obtained from the
748
- object denoted by `E` is not tied to the lifetime of that object.
 
749
 
750
  [*Note 2*: Since the validity of iterators is not tied to the lifetime
751
- of an object whose type models `borrowed_range`, a function can accept
752
- arguments of such a type by value and return iterators obtained from it
753
- without danger of dangling. — *end note*]
754
 
755
  ``` cpp
756
  template<class>
757
- inline constexpr bool enable_borrowed_range = false;
758
  ```
759
 
760
  *Remarks:* Pursuant to [[namespace.std]], users may specialize
761
  `enable_borrowed_range` for cv-unqualified program-defined types. Such
762
  specializations shall be usable in constant expressions [[expr.const]]
@@ -781,30 +1034,29 @@ number of elements in the range can be determined in amortized constant
781
  time using `ranges::size`.
782
 
783
  ``` cpp
784
  template<class T>
785
  concept sized_range =
786
- range<T> &&
787
- requires(T& t) { ranges::size(t); };
788
  ```
789
 
790
  Given an lvalue `t` of type `remove_reference_t<T>`, `T` models
791
  `sized_range` only if
792
 
793
  - `ranges::size(t)` is amortized 𝑂(1), does not modify `t`, and is equal
794
- to `ranges::distance(t)`, and
795
  - if `iterator_t<T>` models `forward_iterator`, `ranges::size(t)` is
796
  well-defined regardless of the evaluation of `ranges::begin(t)`.
797
  \[*Note 1*: `ranges::size(t)` is otherwise not required to be
798
- well-defined after evaluating `ranges::begin(t)`. For example,
799
- `ranges::size(t)` might be well-defined for a `sized_range` whose
800
- iterator type does not model `forward_iterator` only if evaluated
801
- before the first call to `ranges::begin(t)`. — *end note*]
802
 
803
  ``` cpp
804
  template<class>
805
- inline constexpr bool disable_sized_range = false;
806
  ```
807
 
808
  *Remarks:* Pursuant to [[namespace.std]], users may specialize
809
  `disable_sized_range` for cv-unqualified program-defined types. Such
810
  specializations shall be usable in constant expressions [[expr.const]]
@@ -815,51 +1067,66 @@ library that satisfy but do not in fact model
815
  `sized_range`. — *end note*]
816
 
817
  ### Views <a id="range.view">[[range.view]]</a>
818
 
819
  The `view` concept specifies the requirements of a `range` type that has
820
- constant time move construction, move assignment, and destruction; that
821
- is, the cost of these operations is independent of the number of
822
- elements in the `view`.
823
 
824
  ``` cpp
825
  template<class T>
826
  concept view =
827
- range<T> && movable<T> && default_initializable<T> && enable_view<T>;
828
  ```
829
 
830
  `T` models `view` only if:
831
 
832
  - `T` has 𝑂(1) move construction; and
833
- - `T` has 𝑂(1) move assignment; and
834
- - `T` has 𝑂(1) destruction; and
 
 
 
835
  - `copy_constructible<T>` is `false`, or `T` has 𝑂(1) copy construction;
836
  and
837
- - `copyable<T>` is `false`, or `T` has 𝑂(1) copy assignment.
 
 
 
 
838
 
839
  [*Example 1*:
840
 
841
- Examples of `view`s are:
842
 
843
  - A `range` type that wraps a pair of iterators.
844
  - A `range` type that holds its elements by `shared_ptr` and shares
845
  ownership with all its copies.
846
  - A `range` type that generates its elements on demand.
847
 
848
- Most containers [[containers]] are not views since destruction of the
849
- container destroys the elements, which cannot be done in constant time.
 
850
 
851
  — *end example*]
852
 
853
  Since the difference between `range` and `view` is largely semantic, the
854
  two are differentiated with the help of `enable_view`.
855
 
856
  ``` cpp
857
  template<class T>
858
- inline constexpr bool enable_view = derived_from<T, view_base>;
 
 
 
859
  ```
860
 
 
 
 
 
 
861
  *Remarks:* Pursuant to [[namespace.std]], users may specialize
862
  `enable_view` to `true` for cv-unqualified program-defined types which
863
  model `view`, and `false` for types which do not. Such specializations
864
  shall be usable in constant expressions [[expr.const]] and have type
865
  `const bool`.
@@ -892,11 +1159,11 @@ template<class T>
892
  concept random_access_range =
893
  bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
894
  ```
895
 
896
  `contiguous_range` additionally requires that the `ranges::data`
897
- customization point [[range.prim.data]] is usable with the range.
898
 
899
  ``` cpp
900
  template<class T>
901
  concept contiguous_range =
902
  random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
@@ -919,23 +1186,45 @@ which `ranges::begin` and `ranges::end` return objects of the same type.
919
  template<class T>
920
  concept common_range =
921
  range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
922
  ```
923
 
 
 
 
 
 
 
 
 
924
  The `viewable_range` concept specifies the requirements of a `range`
925
- type that can be converted to a `view` safely.
926
 
927
  ``` cpp
928
  template<class T>
929
  concept viewable_range =
930
- range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);
 
 
 
 
 
 
 
 
 
 
 
 
931
  ```
932
 
933
  ## Range utilities <a id="range.utility">[[range.utility]]</a>
934
 
935
- The components in this subclause are general utilities for representing
936
- and manipulating ranges.
 
 
937
 
938
  ### Helper concepts <a id="range.utility.helpers">[[range.utility.helpers]]</a>
939
 
940
  Many of the types in subclause  [[range.utility]] are specified in terms
941
  of the following exposition-only concepts:
@@ -950,40 +1239,67 @@ template<class R>
950
  template<class I>
951
  concept has-arrow = // exposition only
952
  input_iterator<I> && (is_pointer_v<I> || requires(I i) { i.operator->(); });
953
 
954
  template<class T, class U>
955
- concept not-same-as = // exposition only
956
  !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
 
 
 
 
 
957
  ```
958
 
959
  ### View interface <a id="view.interface">[[view.interface]]</a>
960
 
961
- The class template `view_interface` is a helper for defining `view`-like
 
 
962
  types that offer a container-like interface. It is parameterized with
963
  the type that is derived from it.
964
 
965
  ``` cpp
966
  namespace std::ranges {
967
  template<class D>
968
  requires is_class_v<D> && same_as<D, remove_cv_t<D>>
969
- class view_interface : public view_base {
970
  private:
971
  constexpr D& derived() noexcept { // exposition only
972
  return static_cast<D&>(*this);
973
  }
974
  constexpr const D& derived() const noexcept { // exposition only
975
  return static_cast<const D&>(*this);
976
  }
 
977
  public:
978
- constexpr bool empty() requires forward_range<D> {
 
 
 
979
  return ranges::begin(derived()) == ranges::end(derived());
980
  }
981
- constexpr bool empty() const requires forward_range<const D> {
 
 
 
982
  return ranges::begin(derived()) == ranges::end(derived());
983
  }
984
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985
  constexpr explicit operator bool()
986
  requires requires { ranges::empty(derived()); } {
987
  return !ranges::empty(derived());
988
  }
989
  constexpr explicit operator bool() const
@@ -999,15 +1315,15 @@ namespace std::ranges {
999
  return to_address(ranges::begin(derived()));
1000
  }
1001
 
1002
  constexpr auto size() requires forward_range<D> &&
1003
  sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
1004
- return ranges::end(derived()) - ranges::begin(derived());
1005
  }
1006
  constexpr auto size() const requires forward_range<const D> &&
1007
  sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
1008
- return ranges::end(derived()) - ranges::begin(derived());
1009
  }
1010
 
1011
  constexpr decltype(auto) front() requires forward_range<D>;
1012
  constexpr decltype(auto) front() const requires forward_range<const D>;
1013
 
@@ -1038,99 +1354,87 @@ shall be complete, and model both `derived_from<view_interface<D>>` and
1038
  ``` cpp
1039
  constexpr decltype(auto) front() requires forward_range<D>;
1040
  constexpr decltype(auto) front() const requires forward_range<const D>;
1041
  ```
1042
 
1043
- *Preconditions:* `!empty()`.
1044
 
1045
  *Effects:* Equivalent to: `return *ranges::begin(`*`derived`*`());`
1046
 
1047
  ``` cpp
1048
  constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
1049
  constexpr decltype(auto) back() const
1050
  requires bidirectional_range<const D> && common_range<const D>;
1051
  ```
1052
 
1053
- *Preconditions:* `!empty()`.
1054
 
1055
  *Effects:* Equivalent to:
1056
  `return *ranges::prev(ranges::end(`*`derived`*`()));`
1057
 
1058
  ### Sub-ranges <a id="range.subrange">[[range.subrange]]</a>
1059
 
 
 
1060
  The `subrange` class template combines together an iterator and a
1061
  sentinel into a single object that models the `view` concept.
1062
  Additionally, it models the `sized_range` concept when the final
1063
  template parameter is `subrange_kind::sized`.
1064
 
1065
  ``` cpp
1066
  namespace std::ranges {
 
 
 
 
 
1067
  template<class From, class To>
1068
  concept convertible-to-non-slicing = // exposition only
1069
  convertible_to<From, To> &&
1070
- !(is_pointer_v<decay_t<From>> &&
1071
- is_pointer_v<decay_t<To>> &&
1072
- not-same-as<remove_pointer_t<decay_t<From>>, remove_pointer_t<decay_t<To>>>);
1073
-
1074
- template<class T>
1075
- concept pair-like = // exposition only
1076
- !is_reference_v<T> && requires(T t) {
1077
- typename tuple_size<T>::type; // ensures tuple_size<T> is complete
1078
- requires derived_from<tuple_size<T>, integral_constant<size_t, 2>>;
1079
- typename tuple_element_t<0, remove_const_t<T>>;
1080
- typename tuple_element_t<1, remove_const_t<T>>;
1081
- { get<0>(t) } -> convertible_to<const tuple_element_t<0, T>&>;
1082
- { get<1>(t) } -> convertible_to<const tuple_element_t<1, T>&>;
1083
- };
1084
 
1085
  template<class T, class U, class V>
1086
  concept pair-like-convertible-from = // exposition only
1087
- !range<T> && pair-like<T> &&
1088
  constructible_from<T, U, V> &&
1089
  convertible-to-non-slicing<U, tuple_element_t<0, T>> &&
1090
  convertible_to<V, tuple_element_t<1, T>>;
1091
 
1092
- template<class T>
1093
- concept iterator-sentinel-pair = // exposition only
1094
- !range<T> && pair-like<T> &&
1095
- sentinel_for<tuple_element_t<1, T>, tuple_element_t<0, T>>;
1096
-
1097
  template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
1098
  sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
1099
  requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
1100
  class subrange : public view_interface<subrange<I, S, K>> {
1101
  private:
1102
  static constexpr bool StoreSize = // exposition only
1103
  K == subrange_kind::sized && !sized_sentinel_for<S, I>;
1104
  I begin_ = I(); // exposition only
1105
  S end_ = S(); // exposition only
1106
  make-unsigned-like-t<iter_difference_t<I>> size_ = 0; // exposition only; present only
1107
- // when StoreSize is true
1108
  public:
1109
- subrange() = default;
1110
 
1111
  constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
1112
 
1113
  constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
1114
  make-unsigned-like-t<iter_difference_t<I>> n)
1115
  requires (K == subrange_kind::sized);
1116
 
1117
- template<not-same-as<subrange> R>
1118
  requires borrowed_range<R> &&
1119
  convertible-to-non-slicing<iterator_t<R>, I> &&
1120
  convertible_to<sentinel_t<R>, S>
1121
  constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
1122
 
1123
  template<borrowed_range R>
1124
  requires convertible-to-non-slicing<iterator_t<R>, I> &&
1125
  convertible_to<sentinel_t<R>, S>
1126
  constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
1127
  requires (K == subrange_kind::sized)
1128
- : subrange{ranges::begin(r), ranges::end(r), n}
1129
- {}
1130
 
1131
- template<not-same-as<subrange> PairLike>
1132
  requires pair-like-convertible-from<PairLike, const I&, const S&>
1133
  constexpr operator PairLike() const;
1134
 
1135
  constexpr I begin() const requires copyable<I>;
1136
  [[nodiscard]] constexpr I begin() requires (!copyable<I>);
@@ -1153,38 +1457,19 @@ namespace std::ranges {
1153
 
1154
  template<input_or_output_iterator I, sentinel_for<I> S>
1155
  subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) ->
1156
  subrange<I, S, subrange_kind::sized>;
1157
 
1158
- template<iterator-sentinel-pair P>
1159
- subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
1160
-
1161
- template<iterator-sentinel-pair P>
1162
- subrange(P, make-unsigned-like-t<iter_difference_t<tuple_element_t<0, P>>>) ->
1163
- subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
1164
-
1165
  template<borrowed_range R>
1166
  subrange(R&&) ->
1167
  subrange<iterator_t<R>, sentinel_t<R>,
1168
  (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
1169
  ? subrange_kind::sized : subrange_kind::unsized>;
1170
 
1171
  template<borrowed_range R>
1172
  subrange(R&&, make-unsigned-like-t<range_difference_t<R>>) ->
1173
  subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
1174
-
1175
- template<size_t N, class I, class S, subrange_kind K>
1176
- requires (N < 2)
1177
- constexpr auto get(const subrange<I, S, K>& r);
1178
-
1179
- template<size_t N, class I, class S, subrange_kind K>
1180
- requires (N < 2)
1181
- constexpr auto get(subrange<I, S, K>&& r);
1182
- }
1183
-
1184
- namespace std {
1185
- using ranges::get;
1186
  }
1187
  ```
1188
 
1189
  #### Constructors and conversions <a id="range.subrange.ctor">[[range.subrange.ctor]]</a>
1190
 
@@ -1202,35 +1487,36 @@ constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
1202
  make-unsigned-like-t<iter_difference_t<I>> n)
1203
  requires (K == subrange_kind::sized);
1204
  ```
1205
 
1206
  *Preconditions:* \[`i`, `s`) is a valid range, and
1207
- `n == `*`to-unsigned-like`*`(ranges::distance(i, s))`.
1208
 
1209
  *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
1210
  `s`. If *StoreSize* is `true`, initializes *size\_* with `n`.
1211
 
1212
  [*Note 1*: Accepting the length of the range and storing it to later
1213
  return from `size()` enables `subrange` to model `sized_range` even when
1214
  it stores an iterator and sentinel that do not model
1215
  `sized_sentinel_for`. — *end note*]
1216
 
1217
  ``` cpp
1218
- template<not-same-as<subrange> R>
1219
  requires borrowed_range<R> &&
1220
  convertible-to-non-slicing<iterator_t<R>, I> &&
1221
  convertible_to<sentinel_t<R>, S>
1222
  constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
1223
  ```
1224
 
1225
  *Effects:* Equivalent to:
1226
 
1227
- - If *StoreSize* is `true`, `subrange{r, ranges::size(r)}`.
1228
- - Otherwise, `subrange{ranges::begin(r), ranges::end(r)}`.
 
1229
 
1230
  ``` cpp
1231
- template<not-same-as<subrange> PairLike>
1232
  requires pair-like-convertible-from<PairLike, const I&, const S&>
1233
  constexpr operator PairLike() const;
1234
  ```
1235
 
1236
  *Effects:* Equivalent to: `return PairLike(`*`begin_`*`, `*`end_`*`);`
@@ -1313,28 +1599,29 @@ return tmp;
1313
  constexpr subrange& advance(iter_difference_t<I> n);
1314
  ```
1315
 
1316
  *Effects:* Equivalent to:
1317
 
1318
- - If *StoreSize* is `true`,
1319
  ``` cpp
 
 
 
 
 
 
 
 
 
1320
  auto d = n - ranges::advance(begin_, n, end_);
1321
- if (d >= 0)
1322
  size_ -= to-unsigned-like(d);
1323
- else
1324
- size_ += to-unsigned-like(-d);
1325
- return *this;
1326
- ```
1327
- - Otherwise,
1328
- ``` cpp
1329
- ranges::advance(begin_, n, end_);
1330
  return *this;
1331
  ```
1332
 
1333
  ``` cpp
1334
  template<size_t N, class I, class S, subrange_kind K>
1335
- requires (N < 2)
1336
  constexpr auto get(const subrange<I, S, K>& r);
1337
  template<size_t N, class I, class S, subrange_kind K>
1338
  requires (N < 2)
1339
  constexpr auto get(subrange<I, S, K>&& r);
1340
  ```
@@ -1348,24 +1635,23 @@ else
1348
  return r.end();
1349
  ```
1350
 
1351
  ### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
1352
 
1353
- The tag type `dangling` is used together with the template aliases
1354
- `borrowed_iterator_t` and `borrowed_subrange_t` to indicate that an
1355
- algorithm that typically returns an iterator into or subrange of a
1356
- `range` argument does not return an iterator or subrange which could
1357
- potentially reference a range whose lifetime has ended for a particular
1358
- rvalue `range` argument which does not model `borrowed_range`
1359
- [[range.range]].
1360
 
1361
  ``` cpp
1362
  namespace std::ranges {
1363
  struct dangling {
1364
  constexpr dangling() noexcept = default;
1365
- template<class... Args>
1366
- constexpr dangling(Args&&...) noexcept { }
1367
  };
1368
  }
1369
  ```
1370
 
1371
  [*Example 1*:
@@ -1375,39 +1661,256 @@ vector<int> f();
1375
  auto result1 = ranges::find(f(), 42); // #1
1376
  static_assert(same_as<decltype(result1), ranges::dangling>);
1377
  auto vec = f();
1378
  auto result2 = ranges::find(vec, 42); // #2
1379
  static_assert(same_as<decltype(result2), vector<int>::iterator>);
1380
- auto result3 = ranges::find(subrange{vec}, 42); // #3
1381
  static_assert(same_as<decltype(result3), vector<int>::iterator>);
1382
  ```
1383
 
1384
  The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
1385
- is an rvalue `vector`; the `vector` could potentially be destroyed
1386
  before a returned iterator is dereferenced. However, the calls at \#2
1387
  and \#3 both return iterators since the lvalue `vec` and specializations
1388
  of `subrange` model `borrowed_range`.
1389
 
1390
  — *end example*]
1391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1392
  ## Range factories <a id="range.factories">[[range.factories]]</a>
1393
 
1394
- This subclause defines *range factories*, which are utilities to create
1395
- a `view`.
 
 
1396
 
1397
  Range factories are declared in namespace `std::ranges::views`.
1398
 
1399
  ### Empty view <a id="range.empty">[[range.empty]]</a>
1400
 
1401
  #### Overview <a id="range.empty.overview">[[range.empty.overview]]</a>
1402
 
1403
- `empty_view` produces a `view` of no elements of a particular type.
1404
 
1405
  [*Example 1*:
1406
 
1407
  ``` cpp
1408
- empty_view<int> e;
1409
  static_assert(ranges::empty(e));
1410
  static_assert(0 == e.size());
1411
  ```
1412
 
1413
  — *end example*]
@@ -1431,58 +1934,61 @@ namespace std::ranges {
1431
 
1432
  ### Single view <a id="range.single">[[range.single]]</a>
1433
 
1434
  #### Overview <a id="range.single.overview">[[range.single.overview]]</a>
1435
 
1436
- `single_view` produces a `view` that contains exactly one element of a
1437
  specified value.
1438
 
1439
  The name `views::single` denotes a customization point object
1440
  [[customization.point.object]]. Given a subexpression `E`, the
1441
  expression `views::single(E)` is expression-equivalent to
1442
- `single_view{E}`.
1443
 
1444
  [*Example 1*:
1445
 
1446
  ``` cpp
1447
- single_view s{4};
1448
- for (int i : s)
1449
  cout << i; // prints 4
1450
  ```
1451
 
1452
  — *end example*]
1453
 
1454
  #### Class template `single_view` <a id="range.single.view">[[range.single.view]]</a>
1455
 
1456
  ``` cpp
1457
  namespace std::ranges {
1458
- template<copy_constructible T>
1459
  requires is_object_v<T>
1460
  class single_view : public view_interface<single_view<T>> {
1461
  private:
1462
- semiregular-box<T> value_; // exposition only{} (see [range.semi.wrap])
 
1463
  public:
1464
- single_view() = default;
1465
- constexpr explicit single_view(const T& t);
1466
  constexpr explicit single_view(T&& t);
1467
  template<class... Args>
1468
  requires constructible_from<T, Args...>
1469
- constexpr single_view(in_place_t, Args&&... args);
1470
 
1471
  constexpr T* begin() noexcept;
1472
  constexpr const T* begin() const noexcept;
1473
  constexpr T* end() noexcept;
1474
  constexpr const T* end() const noexcept;
1475
  static constexpr size_t size() noexcept;
1476
  constexpr T* data() noexcept;
1477
  constexpr const T* data() const noexcept;
1478
  };
 
 
 
1479
  }
1480
  ```
1481
 
1482
  ``` cpp
1483
- constexpr explicit single_view(const T& t);
1484
  ```
1485
 
1486
  *Effects:* Initializes *value\_* with `t`.
1487
 
1488
  ``` cpp
@@ -1491,11 +1997,12 @@ constexpr explicit single_view(T&& t);
1491
 
1492
  *Effects:* Initializes *value\_* with `std::move(t)`.
1493
 
1494
  ``` cpp
1495
  template<class... Args>
1496
- constexpr single_view(in_place_t, Args&&... args);
 
1497
  ```
1498
 
1499
  *Effects:* Initializes *value\_* as if by
1500
  *`value_`*`{in_place, std::forward<Args>(args)...}`.
1501
 
@@ -1534,49 +2041,50 @@ constexpr const T* data() const noexcept;
1534
  an initial value.
1535
 
1536
  The name `views::iota` denotes a customization point object
1537
  [[customization.point.object]]. Given subexpressions `E` and `F`, the
1538
  expressions `views::iota(E)` and `views::iota(E, F)` are
1539
- expression-equivalent to `iota_view{E}` and `iota_view{E, F}`,
1540
  respectively.
1541
 
1542
  [*Example 1*:
1543
 
1544
  ``` cpp
1545
- for (int i : iota_view{1, 10})
1546
- cout << i << ' '; // prints: 1 2 3 4 5 6 7 8 9
1547
  ```
1548
 
1549
  — *end example*]
1550
 
1551
  #### Class template `iota_view` <a id="range.iota.view">[[range.iota.view]]</a>
1552
 
1553
  ``` cpp
1554
  namespace std::ranges {
1555
  template<class I>
1556
- concept decrementable = // exposition only
1557
- see below;
1558
  template<class I>
1559
- concept advanceable = // exposition only
1560
- see below;
1561
 
1562
  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
1563
- requires weakly-equality-comparable-with<W, Bound> && semiregular<W>
1564
  class iota_view : public view_interface<iota_view<W, Bound>> {
1565
  private:
1566
  // [range.iota.iterator], class iota_view::iterator
1567
  struct iterator; // exposition only
 
1568
  // [range.iota.sentinel], class iota_view::sentinel
1569
  struct sentinel; // exposition only
 
1570
  W value_ = W(); // exposition only
1571
  Bound bound_ = Bound(); // exposition only
 
1572
  public:
1573
- iota_view() = default;
1574
  constexpr explicit iota_view(W value);
1575
- constexpr iota_view(type_identity_t<W> value,
1576
- type_identity_t<Bound> bound);
1577
- constexpr iota_view(iterator first, sentinel last) : iota_view(*first, last.bound_) {}
1578
 
1579
  constexpr iterator begin() const;
1580
  constexpr auto end() const;
1581
  constexpr iterator end() const requires same_as<W, Bound>;
1582
 
@@ -1604,11 +2112,11 @@ Let `IOTA-DIFF-T(W)` be defined as follows:
1604
 
1605
  The exposition-only *decrementable* concept is equivalent to:
1606
 
1607
  ``` cpp
1608
  template<class I>
1609
- concept decrementable =
1610
  incrementable<I> && requires(I i) {
1611
  { --i } -> same_as<I&>;
1612
  { i-- } -> same_as<I>;
1613
  };
1614
  ```
@@ -1628,11 +2136,11 @@ only if
1628
 
1629
  The exposition-only *advanceable* concept is equivalent to:
1630
 
1631
  ``` cpp
1632
  template<class I>
1633
- concept advanceable =
1634
  decrementable<I> && totally_ordered<I> &&
1635
  requires(I i, const I j, const IOTA-DIFF-T(I) n) {
1636
  { i += n } -> same_as<I&>;
1637
  { i -= n } -> same_as<I&>;
1638
  I(j + n);
@@ -1666,30 +2174,49 @@ value `n` of type `D`. `I` models `advanceable` only if
1666
  ``` cpp
1667
  constexpr explicit iota_view(W value);
1668
  ```
1669
 
1670
  *Preconditions:* `Bound` denotes `unreachable_sentinel_t` or `Bound()`
1671
- is reachable from `value`.
 
1672
 
1673
  *Effects:* Initializes *value\_* with `value`.
1674
 
1675
  ``` cpp
1676
- constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
1677
  ```
1678
 
1679
  *Preconditions:* `Bound` denotes `unreachable_sentinel_t` or `bound` is
1680
  reachable from `value`. When `W` and `Bound` model
1681
  `totally_ordered_with`, then `bool(value <= bound)` is `true`.
1682
 
1683
  *Effects:* Initializes *value\_* with `value` and *bound\_* with
1684
  `bound`.
1685
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1686
  ``` cpp
1687
  constexpr iterator begin() const;
1688
  ```
1689
 
1690
- *Effects:* Equivalent to: `return iterator{`*`value_`*`};`
1691
 
1692
  ``` cpp
1693
  constexpr auto end() const;
1694
  ```
1695
 
@@ -1704,11 +2231,11 @@ else
1704
 
1705
  ``` cpp
1706
  constexpr iterator end() const requires same_as<W, Bound>;
1707
  ```
1708
 
1709
- *Effects:* Equivalent to: `return iterator{bound_};`
1710
 
1711
  ``` cpp
1712
  constexpr auto size() const requires see below;
1713
  ```
1714
 
@@ -1723,33 +2250,35 @@ if constexpr (is-integer-like<W> && is-integer-like<Bound>)
1723
  : to-unsigned-like(bound_) - to-unsigned-like(value_);
1724
  else
1725
  return to-unsigned-like(bound_ - value_);
1726
  ```
1727
 
1728
- *Remarks:* The expression in the *requires-clause* is equivalent to
1729
 
1730
  ``` cpp
1731
- (same_as<W, Bound> && advanceable<W>) || (integral<W> && integral<Bound>) ||
1732
  sized_sentinel_for<Bound, W>
1733
  ```
1734
 
1735
  #### Class `iota_view::iterator` <a id="range.iota.iterator">[[range.iota.iterator]]</a>
1736
 
1737
  ``` cpp
1738
  namespace std::ranges {
1739
  template<weakly_incrementable W, semiregular Bound>
1740
- requires weakly-equality-comparable-with<W, Bound>
1741
  struct iota_view<W, Bound>::iterator {
1742
  private:
1743
  W value_ = W(); // exposition only
 
1744
  public:
1745
  using iterator_concept = see below;
1746
- using iterator_category = input_iterator_tag;
 
1747
  using value_type = W;
1748
  using difference_type = IOTA-DIFF-T(W);
1749
 
1750
- iterator() = default;
1751
  constexpr explicit iterator(W value);
1752
 
1753
  constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
1754
 
1755
  constexpr iterator& operator++();
@@ -1963,11 +2492,16 @@ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
1963
  ``` cpp
1964
  friend constexpr iterator operator+(iterator i, difference_type n)
1965
  requires advanceable<W>;
1966
  ```
1967
 
1968
- *Effects:* Equivalent to: `return i += n;`
 
 
 
 
 
1969
 
1970
  ``` cpp
1971
  friend constexpr iterator operator+(difference_type n, iterator i)
1972
  requires advanceable<W>;
1973
  ```
@@ -1977,11 +2511,16 @@ friend constexpr iterator operator+(difference_type n, iterator i)
1977
  ``` cpp
1978
  friend constexpr iterator operator-(iterator i, difference_type n)
1979
  requires advanceable<W>;
1980
  ```
1981
 
1982
- *Effects:* Equivalent to: `return i -= n;`
 
 
 
 
 
1983
 
1984
  ``` cpp
1985
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
1986
  requires advanceable<W>;
1987
  ```
@@ -2005,14 +2544,15 @@ if constexpr (is-integer-like<W>) {
2005
  #### Class `iota_view::sentinel` <a id="range.iota.sentinel">[[range.iota.sentinel]]</a>
2006
 
2007
  ``` cpp
2008
  namespace std::ranges {
2009
  template<weakly_incrementable W, semiregular Bound>
2010
- requires weakly-equality-comparable-with<W, Bound>
2011
  struct iota_view<W, Bound>::sentinel {
2012
  private:
2013
  Bound bound_ = Bound(); // exposition only
 
2014
  public:
2015
  sentinel() = default;
2016
  constexpr explicit sentinel(Bound bound);
2017
 
2018
  friend constexpr bool operator==(const iterator& x, const sentinel& y);
@@ -2049,22 +2589,356 @@ friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterato
2049
  requires sized_sentinel_for<Bound, W>;
2050
  ```
2051
 
2052
  *Effects:* Equivalent to: `return -(y - x);`
2053
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2054
  ### Istream view <a id="range.istream">[[range.istream]]</a>
2055
 
2056
  #### Overview <a id="range.istream.overview">[[range.istream.overview]]</a>
2057
 
2058
  `basic_istream_view` models `input_range` and reads (using `operator>>`)
2059
  successive elements from its corresponding input stream.
2060
 
 
 
 
 
 
 
 
 
 
 
2061
  [*Example 1*:
2062
 
2063
  ``` cpp
2064
  auto ints = istringstream{"0 1 2 3 4"};
2065
- ranges::copy(istream_view<int>(ints), ostream_iterator<int>{cout, "-"});
2066
  // prints 0-1-2-3-4-
2067
  ```
2068
 
2069
  — *end example*]
2070
 
@@ -2076,32 +2950,29 @@ namespace std::ranges {
2076
  concept stream-extractable = // exposition only
2077
  requires(basic_istream<CharT, Traits>& is, Val& t) {
2078
  is >> t;
2079
  };
2080
 
2081
- template<movable Val, class CharT, class Traits>
2082
  requires default_initializable<Val> &&
2083
  stream-extractable<Val, CharT, Traits>
2084
  class basic_istream_view : public view_interface<basic_istream_view<Val, CharT, Traits>> {
2085
  public:
2086
- basic_istream_view() = default;
2087
  constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
2088
 
2089
- constexpr auto begin()
2090
- {
2091
- if (stream_) {
2092
- *stream_ >> object_;
2093
- }
2094
  return iterator{*this};
2095
  }
2096
 
2097
  constexpr default_sentinel_t end() const noexcept;
2098
 
2099
  private:
 
2100
  struct iterator; // exposition only
2101
- basic_istream<CharT, Traits>* stream_ = nullptr; // exposition only
2102
- Val object_ = Val(); // exposition only
2103
  };
2104
  }
2105
  ```
2106
 
2107
  ``` cpp
@@ -2114,32 +2985,23 @@ constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
2114
  constexpr default_sentinel_t end() const noexcept;
2115
  ```
2116
 
2117
  *Effects:* Equivalent to: `return default_sentinel;`
2118
 
2119
- ``` cpp
2120
- template<class Val, class CharT, class Traits>
2121
- basic_istream_view<Val, CharT, Traits> istream_view(basic_istream<CharT, Traits>& s);
2122
- ```
2123
-
2124
- *Effects:* Equivalent to:
2125
- `return basic_istream_view<Val, CharT, Traits>{s};`
2126
-
2127
- #### Class template `basic_istream_view::iterator` <a id="range.istream.iterator">[[range.istream.iterator]]</a>
2128
 
2129
  ``` cpp
2130
  namespace std::ranges {
2131
  template<movable Val, class CharT, class Traits>
2132
  requires default_initializable<Val> &&
2133
  stream-extractable<Val, CharT, Traits>
2134
- class basic_istream_view<Val, CharT, Traits>::iterator { // exposition only
2135
  public:
2136
  using iterator_concept = input_iterator_tag;
2137
  using difference_type = ptrdiff_t;
2138
  using value_type = Val;
2139
 
2140
- iterator() = default;
2141
  constexpr explicit iterator(basic_istream_view& parent) noexcept;
2142
 
2143
  iterator(const iterator&) = delete;
2144
  iterator(iterator&&) = default;
2145
 
@@ -2152,11 +3014,11 @@ namespace std::ranges {
2152
  Val& operator*() const;
2153
 
2154
  friend bool operator==(const iterator& x, default_sentinel_t);
2155
 
2156
  private:
2157
- basic_istream_view* parent_ = nullptr; // exposition only
2158
  };
2159
  }
2160
  ```
2161
 
2162
  ``` cpp
@@ -2167,48 +3029,43 @@ constexpr explicit iterator(basic_istream_view& parent) noexcept;
2167
 
2168
  ``` cpp
2169
  iterator& operator++();
2170
  ```
2171
 
2172
- *Preconditions:* *`parent_`*`->`*`stream_`*` != nullptr` is `true`.
2173
-
2174
  *Effects:* Equivalent to:
2175
 
2176
  ``` cpp
2177
- *parent_->stream_>> parent_->object_;
2178
  return *this;
2179
  ```
2180
 
2181
  ``` cpp
2182
  void operator++(int);
2183
  ```
2184
 
2185
- *Preconditions:* *`parent_`*`->`*`stream_`*` != nullptr` is `true`.
2186
-
2187
  *Effects:* Equivalent to `++*this`.
2188
 
2189
  ``` cpp
2190
  Val& operator*() const;
2191
  ```
2192
 
2193
- *Preconditions:* *`parent_`*`->`*`stream_`*` != nullptr` is `true`.
2194
-
2195
- *Effects:* Equivalent to: `return `*`parent_`*`->`*`object_`*`;`
2196
 
2197
  ``` cpp
2198
  friend bool operator==(const iterator& x, default_sentinel_t);
2199
  ```
2200
 
2201
- *Effects:* Equivalent to:
2202
- `return x.`*`parent_`*` == nullptr || !*x.`*`parent_`*`->`*`stream_`*`;`
2203
 
2204
  ## Range adaptors <a id="range.adaptors">[[range.adaptors]]</a>
2205
 
2206
- This subclause defines *range adaptors*, which are utilities that
2207
- transform a `range` into a `view` with custom behaviors. These adaptors
2208
- can be chained to create pipelines of range transformations that
2209
- evaluate lazily as the resulting view is iterated.
 
 
2210
 
2211
  Range adaptors are declared in namespace `std::ranges::views`.
2212
 
2213
  The bitwise operator is overloaded for the purpose of creating adaptor
2214
  chain pipelines. The adaptors also support function call syntax with
@@ -2219,123 +3076,260 @@ equivalent semantics.
2219
  ``` cpp
2220
  vector<int> ints{0,1,2,3,4,5};
2221
  auto even = [](int i) { return 0 == i % 2; };
2222
  auto square = [](int i) { return i * i; };
2223
  for (int i : ints | views::filter(even) | views::transform(square)) {
2224
- cout << i << ' '; // prints: 0 4 16
2225
  }
2226
  assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
2227
  ```
2228
 
2229
  — *end example*]
2230
 
2231
  ### Range adaptor objects <a id="range.adaptor.object">[[range.adaptor.object]]</a>
2232
 
2233
  A *range adaptor closure object* is a unary function object that accepts
2234
- a `viewable_range` argument and returns a `view`. For a range adaptor
2235
- closure object `C` and an expression `R` such that `decltype((R))`
2236
- models `viewable_range`, the following expressions are equivalent and
2237
- yield a `view`:
2238
 
2239
  ``` cpp
2240
  C(R)
2241
  R | C
2242
  ```
2243
 
2244
  Given an additional range adaptor closure object `D`, the expression
2245
- `C | D` is well-formed and produces another range adaptor closure object
2246
- such that the following two expressions are equivalent:
 
2247
 
2248
- ``` cpp
2249
- R | C | D
2250
- R | (C | D)
2251
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2252
 
2253
  A *range adaptor object* is a customization point object
2254
  [[customization.point.object]] that accepts a `viewable_range` as its
2255
- first argument and returns a `view`.
2256
 
2257
  If a range adaptor object accepts only one argument, then it is a range
2258
  adaptor closure object.
2259
 
2260
- If a range adaptor object accepts more than one argument, then the
2261
- following expressions are equivalent:
 
 
 
 
 
 
 
2262
 
2263
- ``` cpp
2264
- adaptor(range, args...)
2265
- adaptor(args...)(range)
2266
- range | adaptor(args...)
2267
- ```
 
2268
 
2269
- In this case, `adaptor(args...)` is a range adaptor closure object.
 
 
2270
 
2271
- ### Semiregular wrapper <a id="range.semi.wrap">[[range.semi.wrap]]</a>
2272
 
2273
  Many types in this subclause are specified in terms of an
2274
- exposition-only class template *`semiregular-box`*. `semiregular-box<T>`
2275
- behaves exactly like `optional<T>` with the following differences:
2276
 
2277
- - `semiregular-box<T>` constrains its type parameter `T` with
2278
- `copy_constructible<T> && is_object_v<T>`.
2279
- - If `T` models `default_initializable`, the default constructor of
2280
- `semiregular-box<T>` is equivalent to:
2281
  ``` cpp
2282
- constexpr semiregular-box() noexcept(is_nothrow_default_constructible_v<T>)
2283
- : semiregular-box{in_place}
2284
- { }
2285
  ```
2286
- - If `assignable_from<T&, const T&>` is not modeled, the copy assignment
2287
- operator is equivalent to:
2288
  ``` cpp
2289
- semiregular-box& operator=(const semiregular-box& that)
2290
  noexcept(is_nothrow_copy_constructible_v<T>)
2291
- {
 
2292
  if (that) emplace(*that);
2293
  else reset();
 
2294
  return *this;
2295
  }
2296
  ```
2297
- - If `assignable_from<T&, T>` is not modeled, the move assignment
2298
- operator is equivalent to:
2299
  ``` cpp
2300
- semiregular-box& operator=(semiregular-box&& that)
2301
- noexcept(is_nothrow_move_constructible_v<T>)
2302
- {
2303
  if (that) emplace(std::move(*that));
2304
  else reset();
 
2305
  return *this;
2306
  }
2307
  ```
2308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2309
  ### All view <a id="range.all">[[range.all]]</a>
2310
 
2311
- `views::all` returns a `view` that includes all elements of its `range`
 
 
2312
  argument.
2313
 
2314
  The name `views::all` denotes a range adaptor object
2315
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
2316
  `views::all(E)` is expression-equivalent to:
2317
 
2318
  - `decay-copy(E)` if the decayed type of `E` models `view`.
2319
  - Otherwise, `ref_view{E}` if that expression is well-formed.
2320
- - Otherwise, `subrange{E}`.
2321
 
2322
  #### Class template `ref_view` <a id="range.ref.view">[[range.ref.view]]</a>
2323
 
2324
- `ref_view` is a `view` of the elements of some other `range`.
2325
 
2326
  ``` cpp
2327
  namespace std::ranges {
2328
  template<range R>
2329
  requires is_object_v<R>
2330
  class ref_view : public view_interface<ref_view<R>> {
2331
  private:
2332
- R* r_ = nullptr; // exposition only
2333
- public:
2334
- constexpr ref_view() noexcept = default;
2335
 
2336
- template<not-same-as<ref_view> T>
 
2337
  requires see below
2338
  constexpr ref_view(T&& t);
2339
 
2340
  constexpr R& base() const { return *r_; }
2341
 
@@ -2350,56 +3344,194 @@ namespace std::ranges {
2350
  { return ranges::size(*r_); }
2351
 
2352
  constexpr auto data() const requires contiguous_range<R>
2353
  { return ranges::data(*r_); }
2354
  };
 
2355
  template<class R>
2356
  ref_view(R&) -> ref_view<R>;
2357
  }
2358
  ```
2359
 
2360
  ``` cpp
2361
- template<not-same-as<ref_view> T>
2362
  requires see below
2363
  constexpr ref_view(T&& t);
2364
  ```
2365
 
 
 
 
2366
  *Remarks:* Let *`FUN`* denote the exposition-only functions
2367
 
2368
  ``` cpp
2369
  void FUN(R&);
2370
  void FUN(R&&) = delete;
2371
  ```
2372
 
2373
- The expression in the *requires-clause* is equivalent to
2374
 
2375
  ``` cpp
2376
  convertible_to<T, R&> && requires { FUN(declval<T>()); }
2377
  ```
2378
 
2379
- *Effects:* Initializes *r\_* with
2380
- `addressof(static_cast<R&>(std::forward<T>(t)))`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2381
 
2382
  ### Filter view <a id="range.filter">[[range.filter]]</a>
2383
 
2384
  #### Overview <a id="range.filter.overview">[[range.filter.overview]]</a>
2385
 
2386
- `filter_view` presents a `view` of the elements of an underlying
2387
- sequence that satisfy a predicate.
2388
 
2389
  The name `views::filter` denotes a range adaptor object
2390
  [[range.adaptor.object]]. Given subexpressions `E` and `P`, the
2391
  expression `views::filter(E, P)` is expression-equivalent to
2392
- `filter_view{E, P}`.
2393
 
2394
  [*Example 1*:
2395
 
2396
  ``` cpp
2397
  vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
2398
- filter_view evens{is, [](int i) { return 0 == i % 2; }};
2399
  for (int i : evens)
2400
- cout << i << ' '; // prints: 0 2 4 6
2401
  ```
2402
 
2403
  — *end example*]
2404
 
2405
  #### Class template `filter_view` <a id="range.filter.view">[[range.filter.view]]</a>
@@ -2409,20 +3541,21 @@ namespace std::ranges {
2409
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
2410
  requires view<V> && is_object_v<Pred>
2411
  class filter_view : public view_interface<filter_view<V, Pred>> {
2412
  private:
2413
  V base_ = V(); // exposition only
2414
- semiregular-box<Pred> pred_; // exposition only
2415
 
2416
  // [range.filter.iterator], class filter_view::iterator
2417
  class iterator; // exposition only
 
2418
  // [range.filter.sentinel], class filter_view::sentinel
2419
  class sentinel; // exposition only
2420
 
2421
  public:
2422
- filter_view() = default;
2423
- constexpr filter_view(V base, Pred pred);
2424
 
2425
  constexpr V base() const & requires copy_constructible<V> { return base_; }
2426
  constexpr V base() && { return std::move(base_); }
2427
 
2428
  constexpr const Pred& pred() const;
@@ -2440,11 +3573,11 @@ namespace std::ranges {
2440
  filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
2441
  }
2442
  ```
2443
 
2444
  ``` cpp
2445
- constexpr filter_view(V base, Pred pred);
2446
  ```
2447
 
2448
  *Effects:* Initializes *base\_* with `std::move(base)` and initializes
2449
  *pred\_* with `std::move(pred)`.
2450
 
@@ -2456,11 +3589,11 @@ constexpr const Pred& pred() const;
2456
 
2457
  ``` cpp
2458
  constexpr iterator begin();
2459
  ```
2460
 
2461
- *Preconditions:* `pred_.has_value()`.
2462
 
2463
  *Returns:* `{*this, ranges::find_if(`*`base_`*`, ref(*`*`pred_`*`))}`.
2464
 
2465
  *Remarks:* In order to provide the amortized constant time complexity
2466
  required by the `range` concept when `filter_view` models
@@ -2475,21 +3608,21 @@ namespace std::ranges {
2475
  requires view<V> && is_object_v<Pred>
2476
  class filter_view<V, Pred>::iterator {
2477
  private:
2478
  iterator_t<V> current_ = iterator_t<V>(); // exposition only
2479
  filter_view* parent_ = nullptr; // exposition only
 
2480
  public:
2481
- using iterator_concept = see below;
2482
- using iterator_category = see below;
2483
  using value_type = range_value_t<V>;
2484
  using difference_type = range_difference_t<V>;
2485
 
2486
- iterator() = default;
2487
  constexpr iterator(filter_view& parent, iterator_t<V> current);
2488
 
2489
- constexpr iterator_t<V> base() const &
2490
- requires copyable<iterator_t<V>>;
2491
  constexpr iterator_t<V> base() &&;
2492
  constexpr range_reference_t<V> operator*() const;
2493
  constexpr iterator_t<V> operator->() const
2494
  requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
2495
 
@@ -2503,10 +3636,11 @@ namespace std::ranges {
2503
  friend constexpr bool operator==(const iterator& x, const iterator& y)
2504
  requires equality_comparable<iterator_t<V>>;
2505
 
2506
  friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
2507
  noexcept(noexcept(ranges::iter_move(i.current_)));
 
2508
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
2509
  noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
2510
  requires indirectly_swappable<iterator_t<V>>;
2511
  };
2512
  }
@@ -2522,11 +3656,13 @@ not satisfy the filter predicate.
2522
  `bidirectional_iterator_tag`.
2523
  - Otherwise, if `V` models `forward_range`, then `iterator_concept`
2524
  denotes `forward_iterator_tag`.
2525
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
2526
 
2527
- `iterator::iterator_category` is defined as follows:
 
 
2528
 
2529
  - Let `C` denote the type
2530
  `iterator_traits<iterator_t<V>>::iterator_category`.
2531
  - If `C` models `derived_from<bidirectional_iterator_tag>`, then
2532
  `iterator_category` denotes `bidirectional_iterator_tag`.
@@ -2540,21 +3676,20 @@ constexpr iterator(filter_view& parent, iterator_t<V> current);
2540
 
2541
  *Effects:* Initializes *current\_* with `std::move(current)` and
2542
  *parent\_* with `addressof(parent)`.
2543
 
2544
  ``` cpp
2545
- constexpr iterator_t<V> base() const &
2546
- requires copyable<iterator_t<V>>;
2547
  ```
2548
 
2549
  *Effects:* Equivalent to: `return `*`current_`*`;`
2550
 
2551
  ``` cpp
2552
  constexpr iterator_t<V> base() &&;
2553
  ```
2554
 
2555
- *Effects:* Equivalent to: `return std::move(current_);`
2556
 
2557
  ``` cpp
2558
  constexpr range_reference_t<V> operator*() const;
2559
  ```
2560
 
@@ -2652,10 +3787,11 @@ namespace std::ranges {
2652
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
2653
  requires view<V> && is_object_v<Pred>
2654
  class filter_view<V, Pred>::sentinel {
2655
  private:
2656
  sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
 
2657
  public:
2658
  sentinel() = default;
2659
  constexpr explicit sentinel(filter_view& parent);
2660
 
2661
  constexpr sentinel_t<V> base() const;
@@ -2685,50 +3821,51 @@ friend constexpr bool operator==(const iterator& x, const sentinel& y);
2685
 
2686
  ### Transform view <a id="range.transform">[[range.transform]]</a>
2687
 
2688
  #### Overview <a id="range.transform.overview">[[range.transform.overview]]</a>
2689
 
2690
- `transform_view` presents a `view` of an underlying sequence after
2691
  applying a transformation function to each element.
2692
 
2693
  The name `views::transform` denotes a range adaptor object
2694
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
2695
  expression `views::transform(E, F)` is expression-equivalent to
2696
- `transform_view{E, F}`.
2697
 
2698
  [*Example 1*:
2699
 
2700
  ``` cpp
2701
  vector<int> is{ 0, 1, 2, 3, 4 };
2702
- transform_view squares{is, [](int i) { return i * i; }};
2703
  for (int i : squares)
2704
- cout << i << ' '; // prints: 0 1 4 9 16
2705
  ```
2706
 
2707
  — *end example*]
2708
 
2709
  #### Class template `transform_view` <a id="range.transform.view">[[range.transform.view]]</a>
2710
 
2711
  ``` cpp
2712
  namespace std::ranges {
2713
- template<input_range V, copy_constructible F>
2714
  requires view<V> && is_object_v<F> &&
2715
  regular_invocable<F&, range_reference_t<V>> &&
2716
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
2717
  class transform_view : public view_interface<transform_view<V, F>> {
2718
  private:
2719
  // [range.transform.iterator], class template transform_view::iterator
2720
  template<bool> struct iterator; // exposition only
 
2721
  // [range.transform.sentinel], class template transform_view::sentinel
2722
  template<bool> struct sentinel; // exposition only
2723
 
2724
  V base_ = V(); // exposition only
2725
- semiregular-box<F> fun_; // exposition only
2726
 
2727
  public:
2728
- transform_view() = default;
2729
- constexpr transform_view(V base, F fun);
2730
 
2731
  constexpr V base() const & requires copy_constructible<V> { return base_; }
2732
  constexpr V base() && { return std::move(base_); }
2733
 
2734
  constexpr iterator<false> begin();
@@ -2754,11 +3891,11 @@ namespace std::ranges {
2754
  transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
2755
  }
2756
  ```
2757
 
2758
  ``` cpp
2759
- constexpr transform_view(V base, F fun);
2760
  ```
2761
 
2762
  *Effects:* Initializes *base\_* with `std::move(base)` and *fun\_* with
2763
  `std::move(fun)`.
2764
 
@@ -2830,41 +3967,41 @@ return iterator<true>{*this, ranges::end(base_)};
2830
 
2831
  #### Class template `transform_view::iterator` <a id="range.transform.iterator">[[range.transform.iterator]]</a>
2832
 
2833
  ``` cpp
2834
  namespace std::ranges {
2835
- template<input_range V, copy_constructible F>
2836
  requires view<V> && is_object_v<F> &&
2837
  regular_invocable<F&, range_reference_t<V>> &&
2838
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
2839
  template<bool Const>
2840
  class transform_view<V, F>::iterator {
2841
  private:
2842
- using Parent = // exposition only
2843
- conditional_t<Const, const transform_view, transform_view>;
2844
- using Base = // exposition only
2845
- conditional_t<Const, const V, V>;
2846
- iterator_t<Base> current_ = // exposition only
2847
- iterator_t<Base>();
2848
  Parent* parent_ = nullptr; // exposition only
 
2849
  public:
2850
- using iterator_concept = see below;
2851
- using iterator_category = see below;
2852
  using value_type =
2853
- remove_cvref_t<invoke_result_t<F&, range_reference_t<Base>>>;
2854
  using difference_type = range_difference_t<Base>;
2855
 
2856
- iterator() = default;
2857
  constexpr iterator(Parent& parent, iterator_t<Base> current);
2858
  constexpr iterator(iterator<!Const> i)
2859
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
2860
 
2861
- constexpr iterator_t<Base> base() const &
2862
- requires copyable<iterator_t<Base>>;
2863
  constexpr iterator_t<Base> base() &&;
 
2864
  constexpr decltype(auto) operator*() const
2865
- { return invoke(*parent_->fun_, *current_); }
 
 
2866
 
2867
  constexpr iterator& operator++();
2868
  constexpr void operator++(int);
2869
  constexpr iterator operator++(int) requires forward_range<Base>;
2870
 
@@ -2873,13 +4010,15 @@ namespace std::ranges {
2873
 
2874
  constexpr iterator& operator+=(difference_type n)
2875
  requires random_access_range<Base>;
2876
  constexpr iterator& operator-=(difference_type n)
2877
  requires random_access_range<Base>;
 
2878
  constexpr decltype(auto) operator[](difference_type n) const
2879
- requires random_access_range<Base>
2880
- { return invoke(*parent_->fun_, current_[n]); }
 
2881
 
2882
  friend constexpr bool operator==(const iterator& x, const iterator& y)
2883
  requires equality_comparable<iterator_t<Base>>;
2884
 
2885
  friend constexpr bool operator<(const iterator& x, const iterator& y)
@@ -2899,43 +4038,32 @@ namespace std::ranges {
2899
  requires random_access_range<Base>;
2900
 
2901
  friend constexpr iterator operator-(iterator i, difference_type n)
2902
  requires random_access_range<Base>;
2903
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
2904
- requires random_access_range<Base>;
2905
-
2906
- friend constexpr decltype(auto) iter_move(const iterator& i)
2907
- noexcept(noexcept(invoke(*i.parent_->fun_, *i.current_)))
2908
- {
2909
- if constexpr (is_lvalue_reference_v<decltype(*i)>)
2910
- return std::move(*i);
2911
- else
2912
- return *i;
2913
- }
2914
-
2915
- friend constexpr void iter_swap(const iterator& x, const iterator& y)
2916
- noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
2917
- requires indirectly_swappable<iterator_t<Base>>;
2918
  };
2919
  }
2920
  ```
2921
 
2922
  `iterator::iterator_concept` is defined as follows:
2923
 
2924
- - If `V` models `random_access_range`, then `iterator_concept` denotes
2925
- `random_access_iterator_tag`.
2926
- - Otherwise, if `V` models `bidirectional_range`, then
2927
  `iterator_concept` denotes `bidirectional_iterator_tag`.
2928
- - Otherwise, if `V` models `forward_range`, then `iterator_concept`
2929
  denotes `forward_iterator_tag`.
2930
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
2931
 
 
 
2932
  `iterator::iterator_category` is defined as follows: Let `C` denote the
2933
  type `iterator_traits<iterator_t<Base>>::iterator_category`.
2934
 
2935
  - If
2936
- `is_lvalue_reference_v<invoke_result_t<F&, range_reference_t<Base>>>`
2937
  is `true`, then
2938
  - if `C` models `derived_from<contiguous_iterator_tag>`,
2939
  `iterator_category` denotes `random_access_iterator_tag`;
2940
  - otherwise, `iterator_category` denotes `C`.
2941
  - Otherwise, `iterator_category` denotes `input_iterator_tag`.
@@ -2954,21 +4082,20 @@ constexpr iterator(iterator<!Const> i)
2954
 
2955
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
2956
  and *parent\_* with `i.`*`parent_`*.
2957
 
2958
  ``` cpp
2959
- constexpr iterator_t<Base> base() const &
2960
- requires copyable<iterator_t<Base>>;
2961
  ```
2962
 
2963
  *Effects:* Equivalent to: `return `*`current_`*`;`
2964
 
2965
  ``` cpp
2966
  constexpr iterator_t<Base> base() &&;
2967
  ```
2968
 
2969
- *Effects:* Equivalent to: `return std::move(current_);`
2970
 
2971
  ``` cpp
2972
  constexpr iterator& operator++();
2973
  ```
2974
 
@@ -2981,11 +4108,11 @@ return *this;
2981
 
2982
  ``` cpp
2983
  constexpr void operator++(int);
2984
  ```
2985
 
2986
- *Effects:* Equivalent to `++current_`.
2987
 
2988
  ``` cpp
2989
  constexpr iterator operator++(int) requires forward_range<Base>;
2990
  ```
2991
 
@@ -3093,67 +4220,63 @@ friend constexpr iterator operator+(iterator i, difference_type n)
3093
  friend constexpr iterator operator+(difference_type n, iterator i)
3094
  requires random_access_range<Base>;
3095
  ```
3096
 
3097
  *Effects:* Equivalent to:
3098
- `return iterator{*i.`*`parent_`*`, i.`*`current_`*` + n};`
3099
 
3100
  ``` cpp
3101
  friend constexpr iterator operator-(iterator i, difference_type n)
3102
  requires random_access_range<Base>;
3103
  ```
3104
 
3105
  *Effects:* Equivalent to:
3106
- `return iterator{*i.`*`parent_`*`, i.`*`current_`*` - n};`
3107
 
3108
  ``` cpp
3109
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
3110
- requires random_access_range<Base>;
3111
  ```
3112
 
3113
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
3114
 
3115
- ``` cpp
3116
- friend constexpr void iter_swap(const iterator& x, const iterator& y)
3117
- noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
3118
- requires indirectly_swappable<iterator_t<Base>>;
3119
- ```
3120
-
3121
- *Effects:* Equivalent to
3122
- `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
3123
-
3124
  #### Class template `transform_view::sentinel` <a id="range.transform.sentinel">[[range.transform.sentinel]]</a>
3125
 
3126
  ``` cpp
3127
  namespace std::ranges {
3128
- template<input_range V, copy_constructible F>
3129
  requires view<V> && is_object_v<F> &&
3130
  regular_invocable<F&, range_reference_t<V>> &&
3131
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
3132
  template<bool Const>
3133
  class transform_view<V, F>::sentinel {
3134
  private:
3135
- using Parent = // exposition only
3136
- conditional_t<Const, const transform_view, transform_view>;
3137
- using Base = conditional_t<Const, const V, V>; // exposition only
3138
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
3139
  public:
3140
  sentinel() = default;
3141
  constexpr explicit sentinel(sentinel_t<Base> end);
3142
  constexpr sentinel(sentinel<!Const> i)
3143
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3144
 
3145
  constexpr sentinel_t<Base> base() const;
3146
 
3147
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
3148
 
3149
- friend constexpr range_difference_t<Base>
3150
- operator-(const iterator<Const>& x, const sentinel& y)
3151
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
3152
- friend constexpr range_difference_t<Base>
3153
- operator-(const sentinel& y, const iterator<Const>& x)
3154
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
 
 
3155
  };
3156
  }
3157
  ```
3158
 
3159
  ``` cpp
@@ -3174,67 +4297,86 @@ constexpr sentinel_t<Base> base() const;
3174
  ```
3175
 
3176
  *Effects:* Equivalent to: `return `*`end_`*`;`
3177
 
3178
  ``` cpp
3179
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
3180
  ```
3181
 
3182
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
3183
 
3184
  ``` cpp
3185
- friend constexpr range_difference_t<Base>
3186
- operator-(const iterator<Const>& x, const sentinel& y)
3187
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
3188
  ```
3189
 
3190
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
3191
 
3192
  ``` cpp
3193
- friend constexpr range_difference_t<Base>
3194
- operator-(const sentinel& y, const iterator<Const>& x)
3195
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
3196
  ```
3197
 
3198
  *Effects:* Equivalent to: `return y.`*`end_`*` - x.`*`current_`*`;`
3199
 
3200
  ### Take view <a id="range.take">[[range.take]]</a>
3201
 
3202
  #### Overview <a id="range.take.overview">[[range.take.overview]]</a>
3203
 
3204
- `take_view` produces a `view` of the first N elements from another
3205
- `view`, or all the elements if the adapted `view` contains fewer than N.
3206
 
3207
  The name `views::take` denotes a range adaptor object
3208
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
3209
  `remove_cvref_t<decltype((E))>`, and let `D` be
3210
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
3211
  `convertible_to<D>`, `views::take(E, F)` is ill-formed. Otherwise, the
3212
  expression `views::take(E, F)` is expression-equivalent to:
3213
 
3214
- - If `T` is a specialization of `ranges::empty_view`
3215
- [[range.empty.view]], then `((void) F, decay-copy(E))`.
 
3216
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
3217
- is
3218
- - a specialization of `span` [[views.span]] where
3219
- `T::extent == dynamic_extent`,
3220
- - a specialization of `basic_string_view` [[string.view]],
3221
- - a specialization of `ranges::iota_view` [[range.iota.view]], or
3222
- - a specialization of `ranges::subrange` [[range.subrange]],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3223
 
3224
- then
3225
- `T{ranges::begin(E), ranges::begin(E) + min<D>(ranges::size(E), F)}`,
3226
- except that `E` is evaluated only once.
3227
- - Otherwise, `ranges::take_view{E, F}`.
3228
 
3229
  [*Example 1*:
3230
 
3231
  ``` cpp
3232
  vector<int> is{0,1,2,3,4,5,6,7,8,9};
3233
- take_view few{is, 5};
3234
- for (int i : few)
3235
- cout << i << ' '; // prints: 0 1 2 3 4
3236
  ```
3237
 
3238
  — *end example*]
3239
 
3240
  #### Class template `take_view` <a id="range.take.view">[[range.take.view]]</a>
@@ -3244,62 +4386,80 @@ namespace std::ranges {
3244
  template<view V>
3245
  class take_view : public view_interface<take_view<V>> {
3246
  private:
3247
  V base_ = V(); // exposition only
3248
  range_difference_t<V> count_ = 0; // exposition only
 
3249
  // [range.take.sentinel], class template take_view::sentinel
3250
- template<bool> struct sentinel; // exposition only
 
3251
  public:
3252
- take_view() = default;
3253
- constexpr take_view(V base, range_difference_t<V> count);
3254
 
3255
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3256
  constexpr V base() && { return std::move(base_); }
3257
 
3258
  constexpr auto begin() requires (!simple-view<V>) {
3259
  if constexpr (sized_range<V>) {
3260
- if constexpr (random_access_range<V>)
3261
  return ranges::begin(base_);
3262
- else {
3263
- auto sz = size();
3264
- return counted_iterator{ranges::begin(base_), sz};
 
 
 
 
 
 
 
3265
  }
3266
- } else
3267
- return counted_iterator{ranges::begin(base_), count_};
3268
  }
3269
 
3270
  constexpr auto begin() const requires range<const V> {
3271
  if constexpr (sized_range<const V>) {
3272
- if constexpr (random_access_range<const V>)
3273
  return ranges::begin(base_);
3274
- else {
3275
- auto sz = size();
3276
- return counted_iterator{ranges::begin(base_), sz};
 
 
 
 
 
 
 
3277
  }
3278
- } else
3279
- return counted_iterator{ranges::begin(base_), count_};
3280
  }
3281
 
3282
  constexpr auto end() requires (!simple-view<V>) {
3283
  if constexpr (sized_range<V>) {
3284
  if constexpr (random_access_range<V>)
3285
- return ranges::begin(base_) + size();
3286
  else
3287
  return default_sentinel;
3288
- } else
 
 
3289
  return sentinel<false>{ranges::end(base_)};
3290
  }
 
3291
 
3292
  constexpr auto end() const requires range<const V> {
3293
  if constexpr (sized_range<const V>) {
3294
  if constexpr (random_access_range<const V>)
3295
- return ranges::begin(base_) + size();
3296
  else
3297
  return default_sentinel;
3298
- } else
 
 
3299
  return sentinel<true>{ranges::end(base_)};
3300
  }
 
3301
 
3302
  constexpr auto size() requires sized_range<V> {
3303
  auto n = ranges::size(base_);
3304
  return ranges::min(n, static_cast<decltype(n)>(count_));
3305
  }
@@ -3308,20 +4468,22 @@ namespace std::ranges {
3308
  auto n = ranges::size(base_);
3309
  return ranges::min(n, static_cast<decltype(n)>(count_));
3310
  }
3311
  };
3312
 
3313
- template<range R>
3314
  take_view(R&&, range_difference_t<R>)
3315
  -> take_view<views::all_t<R>>;
3316
  }
3317
  ```
3318
 
3319
  ``` cpp
3320
- constexpr take_view(V base, range_difference_t<V> count);
3321
  ```
3322
 
 
 
3323
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
3324
  with `count`.
3325
 
3326
  #### Class template `take_view::sentinel` <a id="range.take.sentinel">[[range.take.sentinel]]</a>
3327
 
@@ -3329,22 +4491,28 @@ with `count`.
3329
  namespace std::ranges {
3330
  template<view V>
3331
  template<bool Const>
3332
  class take_view<V>::sentinel {
3333
  private:
3334
- using Base = conditional_t<Const, const V, V>; // exposition only
3335
- using CI = counted_iterator<iterator_t<Base>>; // exposition only
 
3336
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
3337
  public:
3338
  sentinel() = default;
3339
  constexpr explicit sentinel(sentinel_t<Base> end);
3340
  constexpr sentinel(sentinel<!Const> s)
3341
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3342
 
3343
  constexpr sentinel_t<Base> base() const;
3344
 
3345
- friend constexpr bool operator==(const CI& y, const sentinel& x);
 
 
 
 
3346
  };
3347
  }
3348
  ```
3349
 
3350
  ``` cpp
@@ -3365,35 +4533,39 @@ constexpr sentinel_t<Base> base() const;
3365
  ```
3366
 
3367
  *Effects:* Equivalent to: `return `*`end_`*`;`
3368
 
3369
  ``` cpp
3370
- friend constexpr bool operator==(const CI& y, const sentinel& x);
 
 
 
 
3371
  ```
3372
 
3373
  *Effects:* Equivalent to:
3374
  `return y.count() == 0 || y.base() == x.`*`end_`*`;`
3375
 
3376
  ### Take while view <a id="range.take.while">[[range.take.while]]</a>
3377
 
3378
  #### Overview <a id="range.take.while.overview">[[range.take.while.overview]]</a>
3379
 
3380
- Given a unary predicate `pred` and a `view` `r`, `take_while_view`
3381
- produces a `view` of the range \[`begin(r)`,
3382
  `ranges::find_if_not(r, pred)`).
3383
 
3384
  The name `views::take_while` denotes a range adaptor object
3385
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
3386
  expression `views::take_while(E, F)` is expression-equivalent to
3387
- `take_while_view{E, F}`.
3388
 
3389
  [*Example 1*:
3390
 
3391
  ``` cpp
3392
  auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
3393
  auto small = [](const auto x) noexcept { return x < 5; };
3394
- auto small_ints = istream_view<int>(input) | views::take_while(small);
3395
  for (const auto i : small_ints) {
3396
  cout << i << ' '; // prints 0 1 2 3 4
3397
  }
3398
  auto i = 0;
3399
  input >> i;
@@ -3412,41 +4584,45 @@ namespace std::ranges {
3412
  class take_while_view : public view_interface<take_while_view<V, Pred>> {
3413
  // [range.take.while.sentinel], class template take_while_view::sentinel
3414
  template<bool> class sentinel; // exposition only
3415
 
3416
  V base_ = V(); // exposition only
3417
- semiregular-box<Pred> pred_; // exposition only
3418
 
3419
  public:
3420
- take_while_view() = default;
3421
- constexpr take_while_view(V base, Pred pred);
3422
 
3423
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3424
  constexpr V base() && { return std::move(base_); }
3425
 
3426
  constexpr const Pred& pred() const;
3427
 
3428
  constexpr auto begin() requires (!simple-view<V>)
3429
  { return ranges::begin(base_); }
3430
 
3431
- constexpr auto begin() const requires range<const V>
 
 
3432
  { return ranges::begin(base_); }
3433
 
3434
  constexpr auto end() requires (!simple-view<V>)
3435
  { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
3436
 
3437
- constexpr auto end() const requires range<const V>
 
 
3438
  { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
3439
  };
3440
 
3441
  template<class R, class Pred>
3442
  take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
3443
  }
3444
  ```
3445
 
3446
  ``` cpp
3447
- constexpr take_while_view(V base, Pred pred);
3448
  ```
3449
 
3450
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
3451
  `std::move(pred)`.
3452
 
@@ -3462,24 +4638,30 @@ constexpr const Pred& pred() const;
3462
  namespace std::ranges {
3463
  template<view V, class Pred>
3464
  requires input_range<V> && is_object_v<Pred> &&
3465
  indirect_unary_predicate<const Pred, iterator_t<V>>
3466
  template<bool Const>
3467
- class take_while_view<V, Pred>::sentinel { // exposition only
3468
- using Base = conditional_t<Const, const V, V>; // exposition only
3469
 
3470
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
3471
  const Pred* pred_ = nullptr; // exposition only
 
3472
  public:
3473
  sentinel() = default;
3474
  constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
3475
  constexpr sentinel(sentinel<!Const> s)
3476
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3477
 
3478
  constexpr sentinel_t<Base> base() const { return end_; }
3479
 
3480
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
 
 
 
 
 
3481
  };
3482
  }
3483
  ```
3484
 
3485
  ``` cpp
@@ -3491,56 +4673,79 @@ constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
3491
  ``` cpp
3492
  constexpr sentinel(sentinel<!Const> s)
3493
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
3494
  ```
3495
 
3496
- *Effects:* Initializes *end\_* with `s.`*`end_`* and *pred\_* with
3497
- `s.`*`pred_`*.
3498
 
3499
  ``` cpp
3500
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
 
 
 
 
 
3501
  ```
3502
 
3503
  *Effects:* Equivalent to:
3504
  `return y.`*`end_`*` == x || !invoke(*y.`*`pred_`*`, *x);`
3505
 
3506
  ### Drop view <a id="range.drop">[[range.drop]]</a>
3507
 
3508
  #### Overview <a id="range.drop.overview">[[range.drop.overview]]</a>
3509
 
3510
- `drop_view` produces a `view` excluding the first N elements from
3511
- another `view`, or an empty range if the adapted `view` contains fewer
3512
- than N elements.
3513
 
3514
  The name `views::drop` denotes a range adaptor object
3515
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
3516
  `remove_cvref_t<decltype((E))>`, and let `D` be
3517
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
3518
  `convertible_to<D>`, `views::drop(E, F)` is ill-formed. Otherwise, the
3519
  expression `views::drop(E, F)` is expression-equivalent to:
3520
 
3521
- - If `T` is a specialization of `ranges::empty_view`
3522
- [[range.empty.view]], then `((void) F, decay-copy(E))`.
 
3523
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
3524
  is
3525
- - a specialization of `span` [[views.span]] where
3526
- `T::extent == dynamic_extent`,
3527
  - a specialization of `basic_string_view` [[string.view]],
3528
- - a specialization of `ranges::iota_view` [[range.iota.view]], or
3529
- - a specialization of `ranges::subrange` [[range.subrange]],
 
3530
 
3531
  then
3532
- `T{ranges::begin(E) + min<D>(ranges::size(E), F), ranges::end(E)}`,
3533
- except that `E` is evaluated only once.
3534
- - Otherwise, `ranges::drop_view{E, F}`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3535
 
3536
  [*Example 1*:
3537
 
3538
  ``` cpp
3539
  auto ints = views::iota(0) | views::take(10);
3540
- auto latter_half = drop_view{ints, 5};
3541
- for (auto i : latter_half) {
3542
  cout << i << ' '; // prints 5 6 7 8 9
3543
  }
3544
  ```
3545
 
3546
  — *end example*]
@@ -3550,44 +4755,40 @@ for (auto i : latter_half) {
3550
  ``` cpp
3551
  namespace std::ranges {
3552
  template<view V>
3553
  class drop_view : public view_interface<drop_view<V>> {
3554
  public:
3555
- drop_view() = default;
3556
- constexpr drop_view(V base, range_difference_t<V> count);
3557
 
3558
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3559
  constexpr V base() && { return std::move(base_); }
3560
 
3561
  constexpr auto begin()
3562
- requires (!(simple-view<V> && random_access_range<V>));
 
3563
  constexpr auto begin() const
3564
- requires random_access_range<const V>;
3565
 
3566
- constexpr auto end()
3567
- requires (!simple-view<V>)
3568
  { return ranges::end(base_); }
3569
 
3570
- constexpr auto end() const
3571
- requires range<const V>
3572
  { return ranges::end(base_); }
3573
 
3574
- constexpr auto size()
3575
- requires sized_range<V>
3576
- {
3577
  const auto s = ranges::size(base_);
3578
  const auto c = static_cast<decltype(s)>(count_);
3579
  return s < c ? 0 : s - c;
3580
  }
3581
 
3582
- constexpr auto size() const
3583
- requires sized_range<const V>
3584
- {
3585
  const auto s = ranges::size(base_);
3586
  const auto c = static_cast<decltype(s)>(count_);
3587
  return s < c ? 0 : s - c;
3588
  }
 
3589
  private:
3590
  V base_ = V(); // exposition only
3591
  range_difference_t<V> count_ = 0; // exposition only
3592
  };
3593
 
@@ -3595,27 +4796,28 @@ namespace std::ranges {
3595
  drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
3596
  }
3597
  ```
3598
 
3599
  ``` cpp
3600
- constexpr drop_view(V base, range_difference_t<V> count);
3601
  ```
3602
 
3603
  *Preconditions:* `count >= 0` is `true`.
3604
 
3605
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
3606
  with `count`.
3607
 
3608
  ``` cpp
3609
  constexpr auto begin()
3610
- requires (!(simple-view<V> && random_access_range<V>));
 
3611
  constexpr auto begin() const
3612
- requires random_access_range<const V>;
3613
  ```
3614
 
3615
  *Returns:*
3616
- `ranges::next(ranges::begin(base_), count_, ranges::end(base_))`.
3617
 
3618
  *Remarks:* In order to provide the amortized constant-time complexity
3619
  required by the `range` concept when `drop_view` models `forward_range`,
3620
  the first overload caches the result within the `drop_view` for use on
3621
  subsequent calls.
@@ -3625,25 +4827,25 @@ would have quadratic iteration complexity. — *end note*]
3625
 
3626
  ### Drop while view <a id="range.drop.while">[[range.drop.while]]</a>
3627
 
3628
  #### Overview <a id="range.drop.while.overview">[[range.drop.while.overview]]</a>
3629
 
3630
- Given a unary predicate `pred` and a `view` `r`, `drop_while_view`
3631
- produces a `view` of the range \[`ranges::find_if_not(r, pred)`,
3632
  `ranges::end(r)`).
3633
 
3634
  The name `views::drop_while` denotes a range adaptor object
3635
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
3636
  expression `views::drop_while(E, F)` is expression-equivalent to
3637
- `drop_while_view{E, F}`.
3638
 
3639
  [*Example 1*:
3640
 
3641
  ``` cpp
3642
- constexpr auto source = " \t \t \t hello there";
3643
  auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
3644
- auto skip_ws = drop_while_view{source, is_invisible};
3645
  for (auto c : skip_ws) {
3646
  cout << c; // prints hello there with no leading space
3647
  }
3648
  ```
3649
 
@@ -3656,35 +4858,34 @@ namespace std::ranges {
3656
  template<view V, class Pred>
3657
  requires input_range<V> && is_object_v<Pred> &&
3658
  indirect_unary_predicate<const Pred, iterator_t<V>>
3659
  class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
3660
  public:
3661
- drop_while_view() = default;
3662
- constexpr drop_while_view(V base, Pred pred);
3663
 
3664
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3665
  constexpr V base() && { return std::move(base_); }
3666
 
3667
  constexpr const Pred& pred() const;
3668
 
3669
  constexpr auto begin();
3670
 
3671
- constexpr auto end()
3672
- { return ranges::end(base_); }
3673
 
3674
  private:
3675
  V base_ = V(); // exposition only
3676
- semiregular-box<Pred> pred_; // exposition only
3677
  };
3678
 
3679
  template<class R, class Pred>
3680
  drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
3681
  }
3682
  ```
3683
 
3684
  ``` cpp
3685
- constexpr drop_while_view(V base, Pred pred);
3686
  ```
3687
 
3688
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
3689
  `std::move(pred)`.
3690
 
@@ -3696,11 +4897,13 @@ constexpr const Pred& pred() const;
3696
 
3697
  ``` cpp
3698
  constexpr auto begin();
3699
  ```
3700
 
3701
- *Returns:* `ranges::find_if_not(base_, cref(*pred_))`.
 
 
3702
 
3703
  *Remarks:* In order to provide the amortized constant-time complexity
3704
  required by the `range` concept when `drop_while_view` models
3705
  `forward_range`, the first call caches the result within the
3706
  `drop_while_view` for use on subsequent calls.
@@ -3711,67 +4914,75 @@ complexity. — *end note*]
3711
 
3712
  ### Join view <a id="range.join">[[range.join]]</a>
3713
 
3714
  #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
3715
 
3716
- `join_view` flattens a `view` of ranges into a `view`.
3717
 
3718
  The name `views::join` denotes a range adaptor object
3719
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
3720
- `views::join(E)` is expression-equivalent to `join_view{E}`.
 
3721
 
3722
  [*Example 1*:
3723
 
3724
  ``` cpp
3725
  vector<string> ss{"hello", " ", "world", "!"};
3726
- join_view greeting{ss};
3727
- for (char ch : greeting)
3728
- cout << ch; // prints: hello world!
3729
  ```
3730
 
3731
  — *end example*]
3732
 
3733
  #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
3734
 
3735
  ``` cpp
3736
  namespace std::ranges {
3737
  template<input_range V>
3738
- requires view<V> && input_range<range_reference_t<V>> &&
3739
- (is_reference_v<range_reference_t<V>> ||
3740
- view<range_value_t<V>>)
3741
  class join_view : public view_interface<join_view<V>> {
3742
  private:
3743
- using InnerRng = // exposition only
3744
- range_reference_t<V>;
3745
  // [range.join.iterator], class template join_view::iterator
3746
  template<bool Const>
3747
  struct iterator; // exposition only
 
3748
  // [range.join.sentinel], class template join_view::sentinel
3749
  template<bool Const>
3750
  struct sentinel; // exposition only
3751
 
3752
  V base_ = V(); // exposition only
3753
- views::all_t<InnerRng> inner_ = // exposition only, present only when !is_reference_v<InnerRng>
3754
- views::all_t<InnerRng>();
 
 
 
 
3755
  public:
3756
- join_view() = default;
3757
  constexpr explicit join_view(V base);
3758
 
3759
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3760
  constexpr V base() && { return std::move(base_); }
3761
 
3762
  constexpr auto begin() {
 
3763
  constexpr bool use_const = simple-view<V> &&
3764
- is_reference_v<range_reference_t<V>>;
3765
  return iterator<use_const>{*this, ranges::begin(base_)};
 
 
 
 
3766
  }
3767
 
3768
  constexpr auto begin() const
3769
- requires input_range<const V> &&
3770
- is_reference_v<range_reference_t<const V>> {
3771
- return iterator<true>{*this, ranges::begin(base_)};
3772
- }
3773
 
3774
  constexpr auto end() {
3775
  if constexpr (forward_range<V> &&
3776
  is_reference_v<InnerRng> && forward_range<InnerRng> &&
3777
  common_range<V> && common_range<InnerRng>)
@@ -3779,15 +4990,14 @@ namespace std::ranges {
3779
  else
3780
  return sentinel<simple-view<V>>{*this};
3781
  }
3782
 
3783
  constexpr auto end() const
3784
- requires input_range<const V> &&
3785
- is_reference_v<range_reference_t<const V>> {
3786
- if constexpr (forward_range<const V> &&
3787
  is_reference_v<range_reference_t<const V>> &&
3788
- forward_range<range_reference_t<const V>> &&
 
3789
  common_range<const V> &&
3790
  common_range<range_reference_t<const V>>)
3791
  return iterator<true>{*this, ranges::end(base_)};
3792
  else
3793
  return sentinel<true>{*this};
@@ -3808,47 +5018,53 @@ constexpr explicit join_view(V base);
3808
  #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
3809
 
3810
  ``` cpp
3811
  namespace std::ranges {
3812
  template<input_range V>
3813
- requires view<V> && input_range<range_reference_t<V>> &&
3814
- (is_reference_v<range_reference_t<V>> ||
3815
- view<range_value_t<V>>)
3816
  template<bool Const>
3817
  struct join_view<V>::iterator {
3818
  private:
3819
- using Parent = // exposition only
3820
- conditional_t<Const, const join_view, join_view>;
3821
- using Base = conditional_t<Const, const V, V>; // exposition only
 
3822
 
3823
  static constexpr bool ref-is-glvalue = // exposition only
3824
  is_reference_v<range_reference_t<Base>>;
3825
 
3826
- iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only
3827
- iterator_t<range_reference_t<Base>> inner_ = // exposition only
3828
- iterator_t<range_reference_t<Base>>();
3829
  Parent* parent_ = nullptr; // exposition only
3830
 
3831
  constexpr void satisfy(); // exposition only
 
 
 
 
 
 
 
 
 
3832
  public:
3833
  using iterator_concept = see below;
3834
- using iterator_category = see below;
3835
  using value_type = range_value_t<range_reference_t<Base>>;
3836
  using difference_type = see below;
3837
 
3838
  iterator() = default;
3839
- constexpr iterator(Parent& parent, iterator_t<Base> outer);
3840
  constexpr iterator(iterator<!Const> i)
3841
  requires Const &&
3842
- convertible_to<iterator_t<V>, iterator_t<Base>> &&
3843
- convertible_to<iterator_t<InnerRng>,
3844
- iterator_t<range_reference_t<Base>>>;
3845
 
3846
- constexpr decltype(auto) operator*() const { return *inner_; }
3847
 
3848
- constexpr iterator_t<Base> operator->() const
3849
- requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
3850
 
3851
  constexpr iterator& operator++();
3852
  constexpr void operator++(int);
3853
  constexpr iterator operator++(int)
3854
  requires ref-is-glvalue && forward_range<Base> &&
@@ -3863,50 +5079,53 @@ namespace std::ranges {
3863
  requires ref-is-glvalue && bidirectional_range<Base> &&
3864
  bidirectional_range<range_reference_t<Base>> &&
3865
  common_range<range_reference_t<Base>>;
3866
 
3867
  friend constexpr bool operator==(const iterator& x, const iterator& y)
3868
- requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
3869
  equality_comparable<iterator_t<range_reference_t<Base>>>;
3870
 
3871
  friend constexpr decltype(auto) iter_move(const iterator& i)
3872
- noexcept(noexcept(ranges::iter_move(i.inner_))) {
3873
- return ranges::iter_move(i.inner_);
3874
  }
3875
 
3876
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
3877
- noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
 
3878
  };
3879
  }
3880
  ```
3881
 
3882
  `iterator::iterator_concept` is defined as follows:
3883
 
3884
- - If *`ref-is-glvalue`* is `true` and *`Base`* and
3885
- `range_reference_t<Base>` each model `bidirectional_range`, then
3886
- `iterator_concept` denotes `bidirectional_iterator_tag`.
 
3887
  - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
3888
  `range_reference_t<Base>` each model , then `iterator_concept` denotes
3889
  `forward_iterator_tag`.
3890
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
3891
 
 
 
 
3892
  `iterator::iterator_category` is defined as follows:
3893
 
3894
  - Let *OUTERC* denote
3895
  `iterator_traits<iterator_t<Base>>::iterator_category`, and let
3896
  *INNERC* denote
3897
  `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
3898
- - If *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC* each model
3899
- `derived_from<bidirectional_iterator_tag>`, `iterator_category`
 
3900
  denotes `bidirectional_iterator_tag`.
3901
- - Otherwise, if *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC*
3902
- each model `derived_from<forward_iterator_tag>`, `iterator_category`
3903
- denotes `forward_iterator_tag`.
3904
  - Otherwise, if *OUTERC* and *INNERC* each model
3905
- `derived_from<input_iterator_tag>`, `iterator_category` denotes
3906
- `input_iterator_tag`.
3907
- - Otherwise, `iterator_category` denotes `output_iterator_tag`.
3908
 
3909
  `iterator::difference_type` denotes the type:
3910
 
3911
  ``` cpp
3912
  common_type_t<
@@ -3916,74 +5135,92 @@ common_type_t<
3916
 
3917
  `join_view` iterators use the *`satisfy`* function to skip over empty
3918
  inner ranges.
3919
 
3920
  ``` cpp
3921
- constexpr void satisfy(); // exposition only
 
 
 
 
 
 
 
 
3922
  ```
3923
 
3924
  *Effects:* Equivalent to:
3925
 
3926
  ``` cpp
3927
- auto update_inner = [this](range_reference_t<Base> x) -> auto& {
3928
- if constexpr (ref-is-glvalue) // x is a reference
3929
- return x;
3930
  else
3931
- return (parent_->inner_ = views::all(std::move(x)));
3932
  };
3933
 
3934
- for (; outer_ != ranges::end(parent_->base_); ++outer_) {
3935
- auto& inner = update_inner(*outer_);
3936
  inner_ = ranges::begin(inner);
3937
- if (inner_ != ranges::end(inner))
3938
  return;
3939
  }
3940
  if constexpr (ref-is-glvalue)
3941
- inner_ = iterator_t<range_reference_t<Base>>();
3942
  ```
3943
 
3944
  ``` cpp
3945
- constexpr iterator(Parent& parent, iterator_t<Base> outer);
 
3946
  ```
3947
 
3948
  *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
3949
  with `addressof(parent)`; then calls *`satisfy`*`()`.
3950
 
 
 
 
 
 
 
 
 
3951
  ``` cpp
3952
  constexpr iterator(iterator<!Const> i)
3953
  requires Const &&
3954
- convertible_to<iterator_t<V>, iterator_t<Base>> &&
3955
- convertible_to<iterator_t<InnerRng>,
3956
- iterator_t<range_reference_t<Base>>>;
3957
  ```
3958
 
3959
  *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
3960
  *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
3961
  `i.`*`parent_`*.
3962
 
 
 
 
3963
  ``` cpp
3964
- constexpr iterator_t<Base> operator->() const
3965
- requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
3966
  ```
3967
 
3968
- *Effects:* Equivalent to `return `*`inner_`*`;`
3969
 
3970
  ``` cpp
3971
  constexpr iterator& operator++();
3972
  ```
3973
 
3974
  Let *`inner-range`* be:
3975
 
3976
- - If *ref-is-glvalue* is `true`, `*`*`outer_`*.
3977
- - Otherwise, *`parent_`*`->`*`inner_`*.
3978
 
3979
  *Effects:* Equivalent to:
3980
 
3981
  ``` cpp
3982
- auto&& inner_rng = inner-range;
3983
- if (++inner_ == ranges::end(inner_rng)) {
3984
- ++outer_;
3985
  satisfy();
3986
  }
3987
  return *this;
3988
  ```
3989
 
@@ -4016,14 +5253,14 @@ constexpr iterator& operator--()
4016
 
4017
  *Effects:* Equivalent to:
4018
 
4019
  ``` cpp
4020
  if (outer_ == ranges::end(parent_->base_))
4021
- inner_ = ranges::end(*--outer_);
4022
- while (inner_ == ranges::begin(*outer_))
4023
- inner_ = ranges::end(*--outer_);
4024
- --inner_;
4025
  return *this;
4026
  ```
4027
 
4028
  ``` cpp
4029
  constexpr iterator operator--(int)
@@ -4040,48 +5277,573 @@ auto tmp = *this;
4040
  return tmp;
4041
  ```
4042
 
4043
  ``` cpp
4044
  friend constexpr bool operator==(const iterator& x, const iterator& y)
4045
- requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
4046
  equality_comparable<iterator_t<range_reference_t<Base>>>;
4047
  ```
4048
 
4049
  *Effects:* Equivalent to:
4050
  `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
4051
 
4052
  ``` cpp
4053
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
4054
- noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
 
4055
  ```
4056
 
4057
  *Effects:* Equivalent to:
4058
- `return ranges::iter_swap(x.`*`inner_`*`, y.`*`inner_`*`);`
4059
 
4060
  #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
4061
 
4062
  ``` cpp
4063
  namespace std::ranges {
4064
  template<input_range V>
4065
- requires view<V> && input_range<range_reference_t<V>> &&
4066
- (is_reference_v<range_reference_t<V>> ||
4067
- view<range_value_t<V>>)
4068
  template<bool Const>
4069
  struct join_view<V>::sentinel {
4070
  private:
4071
- using Parent = // exposition only
4072
- conditional_t<Const, const join_view, join_view>;
4073
- using Base = conditional_t<Const, const V, V>; // exposition only
4074
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
4075
  public:
4076
  sentinel() = default;
4077
 
4078
  constexpr explicit sentinel(Parent& parent);
4079
  constexpr sentinel(sentinel<!Const> s)
4080
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4081
 
4082
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4083
  };
4084
  }
4085
  ```
4086
 
4087
  ``` cpp
@@ -4096,44 +5858,45 @@ constexpr sentinel(sentinel<!Const> s)
4096
  ```
4097
 
4098
  *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
4099
 
4100
  ``` cpp
4101
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
4102
  ```
4103
 
4104
- *Effects:* Equivalent to: `return x.`*`outer_`*` == y.`*`end_`*`;`
4105
 
4106
- ### Split view <a id="range.split">[[range.split]]</a>
4107
 
4108
- #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
4109
 
4110
- `split_view` takes a `view` and a delimiter, and splits the `view` into
4111
  subranges on the delimiter. The delimiter can be a single element or a
4112
- `view` of elements.
4113
 
4114
- The name `views::split` denotes a range adaptor object
4115
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
4116
- expression `views::split(E, F)` is expression-equivalent to
4117
- `split_view{E, F}`.
4118
 
4119
  [*Example 1*:
4120
 
4121
  ``` cpp
4122
  string str{"the quick brown fox"};
4123
- split_view sentence{str, ' '};
4124
- for (auto word : sentence) {
4125
  for (char ch : word)
4126
  cout << ch;
4127
  cout << '*';
4128
  }
4129
- // The above prints: the*quick*brown*fox*
4130
  ```
4131
 
4132
  — *end example*]
4133
 
4134
- #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
4135
 
4136
  ``` cpp
4137
  namespace std::ranges {
4138
  template<auto> struct require-constant; // exposition only
4139
 
@@ -4145,46 +5908,54 @@ namespace std::ranges {
4145
 
4146
  template<input_range V, forward_range Pattern>
4147
  requires view<V> && view<Pattern> &&
4148
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4149
  (forward_range<V> || tiny-range<Pattern>)
4150
- class split_view : public view_interface<split_view<V, Pattern>> {
4151
  private:
4152
  V base_ = V(); // exposition only
4153
  Pattern pattern_ = Pattern(); // exposition only
4154
- iterator_t<V> current_ = iterator_t<V>(); // exposition only, present only if !forward_range<V>
4155
- // [range.split.outer], class template split_view::outer-iterator
 
 
 
4156
  template<bool> struct outer-iterator; // exposition only
4157
- // [range.split.inner], class template split_view::inner-iterator
 
4158
  template<bool> struct inner-iterator; // exposition only
 
4159
  public:
4160
- split_view() = default;
4161
- constexpr split_view(V base, Pattern pattern);
 
4162
 
4163
  template<input_range R>
4164
  requires constructible_from<V, views::all_t<R>> &&
4165
  constructible_from<Pattern, single_view<range_value_t<R>>>
4166
- constexpr split_view(R&& r, range_value_t<R> e);
4167
 
4168
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4169
  constexpr V base() && { return std::move(base_); }
4170
 
4171
  constexpr auto begin() {
4172
- if constexpr (forward_range<V>)
4173
- return outer-iterator<simple-view<V>>{*this, ranges::begin(base_)};
4174
- else {
 
4175
  current_ = ranges::begin(base_);
4176
  return outer-iterator<false>{*this};
4177
  }
4178
  }
4179
 
4180
  constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
4181
  return outer-iterator<true>{*this, ranges::begin(base_)};
4182
  }
4183
 
4184
  constexpr auto end() requires forward_range<V> && common_range<V> {
4185
- return outer-iterator<simple-view<V>>{*this, ranges::end(base_)};
 
4186
  }
4187
 
4188
  constexpr auto end() const {
4189
  if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
4190
  return outer-iterator<true>{*this, ranges::end(base_)};
@@ -4192,59 +5963,63 @@ namespace std::ranges {
4192
  return default_sentinel;
4193
  }
4194
  };
4195
 
4196
  template<class R, class P>
4197
- split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
4198
 
4199
  template<input_range R>
4200
- split_view(R&&, range_value_t<R>)
4201
- -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
4202
  }
4203
  ```
4204
 
4205
  ``` cpp
4206
- constexpr split_view(V base, Pattern pattern);
4207
  ```
4208
 
4209
  *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
4210
  with `std::move(pattern)`.
4211
 
4212
  ``` cpp
4213
  template<input_range R>
4214
  requires constructible_from<V, views::all_t<R>> &&
4215
  constructible_from<Pattern, single_view<range_value_t<R>>>
4216
- constexpr split_view(R&& r, range_value_t<R> e);
4217
  ```
4218
 
4219
  *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
4220
- and *pattern\_* with `single_view{std::move(e)}`.
4221
 
4222
- #### Class template `split_view::outer-iterator` <a id="range.split.outer">[[range.split.outer]]</a>
4223
 
4224
  ``` cpp
4225
  namespace std::ranges {
4226
  template<input_range V, forward_range Pattern>
4227
  requires view<V> && view<Pattern> &&
4228
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4229
  (forward_range<V> || tiny-range<Pattern>)
4230
  template<bool Const>
4231
- struct split_view<V, Pattern>::outer-iterator {
4232
  private:
4233
- using Parent = // exposition only
4234
- conditional_t<Const, const split_view, split_view>;
4235
- using Base = // exposition only
4236
- conditional_t<Const, const V, V>;
4237
  Parent* parent_ = nullptr; // exposition only
4238
- iterator_t<Base> current_ = // exposition only, present only if V models forward_range
4239
- iterator_t<Base>();
 
 
 
4240
 
4241
  public:
4242
  using iterator_concept =
4243
  conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
4244
- using iterator_category = input_iterator_tag;
4245
- // [range.split.outer.value], class split_view::outer-iterator::value_type
 
 
 
4246
  struct value_type;
4247
  using difference_type = range_difference_t<Base>;
4248
 
4249
  outer-iterator() = default;
4250
  constexpr explicit outer-iterator(Parent& parent)
@@ -4272,13 +6047,14 @@ namespace std::ranges {
4272
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
4273
  };
4274
  }
4275
  ```
4276
 
4277
- Many of the following specifications refer to the notional member
4278
- *current* of *`outer-iterator`*. *current* is equivalent to *`current_`*
4279
- if `V` models `forward_range`, and `parent_->current_` otherwise.
 
4280
 
4281
  ``` cpp
4282
  constexpr explicit outer-iterator(Parent& parent)
4283
  requires (!forward_range<Base>);
4284
  ```
@@ -4313,18 +6089,31 @@ constexpr outer-iterator& operator++();
4313
 
4314
  *Effects:* Equivalent to:
4315
 
4316
  ``` cpp
4317
  const auto end = ranges::end(parent_->base_);
4318
- if (current == end) return *this;
 
 
 
4319
  const auto [pbegin, pend] = subrange{parent_->pattern_};
4320
  if (pbegin == pend) ++current;
 
 
 
 
 
 
 
 
4321
  else {
4322
  do {
4323
- auto [b, p] = ranges::mismatch(std::move(current), end, pbegin, pend);
4324
- current = std::move(b);
4325
  if (p == pend) {
 
 
 
4326
  break; // The pattern matched; skip it
4327
  }
4328
  } while (++current != end);
4329
  }
4330
  return *this;
@@ -4333,39 +6122,46 @@ return *this;
4333
  ``` cpp
4334
  friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
4335
  requires forward_range<Base>;
4336
  ```
4337
 
4338
- *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
 
 
 
 
4339
 
4340
  ``` cpp
4341
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
4342
  ```
4343
 
4344
  *Effects:* Equivalent to:
4345
- `return x.`*`current`*` == ranges::end(x.`*`parent_`*`->`*`base_`*`);`
4346
 
4347
- #### Class `split_view::outer-iterator::value_type` <a id="range.split.outer.value">[[range.split.outer.value]]</a>
 
 
 
 
4348
 
4349
  ``` cpp
4350
  namespace std::ranges {
4351
  template<input_range V, forward_range Pattern>
4352
  requires view<V> && view<Pattern> &&
4353
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4354
  (forward_range<V> || tiny-range<Pattern>)
4355
  template<bool Const>
4356
- struct split_view<V, Pattern>::outer-iterator<Const>::value_type
4357
  : view_interface<value_type> {
4358
  private:
4359
  outer-iterator i_ = outer-iterator(); // exposition only
 
4360
  public:
4361
  value_type() = default;
4362
  constexpr explicit value_type(outer-iterator i);
4363
 
4364
- constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
4365
- constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
4366
- constexpr default_sentinel_t end() const;
4367
  };
4368
  }
4369
  ```
4370
 
4371
  ``` cpp
@@ -4373,57 +6169,56 @@ constexpr explicit value_type(outer-iterator i);
4373
  ```
4374
 
4375
  *Effects:* Initializes *i\_* with `std::move(i)`.
4376
 
4377
  ``` cpp
4378
- constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
4379
  ```
4380
 
4381
  *Effects:* Equivalent to:
4382
  `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
4383
 
4384
  ``` cpp
4385
- constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
4386
- ```
4387
-
4388
- *Effects:* Equivalent to:
4389
- `return `*`inner-iterator`*`<Const>{std::move(`*`i_`*`)};`
4390
-
4391
- ``` cpp
4392
- constexpr default_sentinel_t end() const;
4393
  ```
4394
 
4395
  *Effects:* Equivalent to: `return default_sentinel;`
4396
 
4397
- #### Class template `split_view::inner-iterator` <a id="range.split.inner">[[range.split.inner]]</a>
4398
 
4399
  ``` cpp
4400
  namespace std::ranges {
4401
  template<input_range V, forward_range Pattern>
4402
  requires view<V> && view<Pattern> &&
4403
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
4404
  (forward_range<V> || tiny-range<Pattern>)
4405
  template<bool Const>
4406
- struct split_view<V, Pattern>::inner-iterator {
4407
  private:
4408
- using Base = conditional_t<Const, const V, V>; // exposition only
4409
  outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
4410
  bool incremented_ = false; // exposition only
 
4411
  public:
4412
  using iterator_concept = typename outer-iterator<Const>::iterator_concept;
4413
- using iterator_category = see below;
 
 
4414
  using value_type = range_value_t<Base>;
4415
  using difference_type = range_difference_t<Base>;
4416
 
4417
  inner-iterator() = default;
4418
  constexpr explicit inner-iterator(outer-iterator<Const> i);
4419
 
 
 
 
4420
  constexpr decltype(auto) operator*() const { return *i_.current; }
4421
 
4422
  constexpr inner-iterator& operator++();
4423
  constexpr decltype(auto) operator++(int) {
4424
- if constexpr (forward_range<V>) {
4425
  auto tmp = *this;
4426
  ++*this;
4427
  return tmp;
4428
  } else
4429
  ++*this;
@@ -4444,11 +6239,13 @@ namespace std::ranges {
4444
  requires indirectly_swappable<iterator_t<Base>>;
4445
  };
4446
  }
4447
  ```
4448
 
4449
- The *typedef-name* `iterator_category` denotes:
 
 
4450
 
4451
  - `forward_iterator_tag` if
4452
  `iterator_traits<iterator_t<Base>>::iterator_category` models
4453
  `derived_from<forward_iterator_tag>`;
4454
  - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
@@ -4457,10 +6254,22 @@ The *typedef-name* `iterator_category` denotes:
4457
  constexpr explicit inner-iterator(outer-iterator<Const> i);
4458
  ```
4459
 
4460
  *Effects:* Initializes *i\_* with `std::move(i)`.
4461
 
 
 
 
 
 
 
 
 
 
 
 
 
4462
  ``` cpp
4463
  constexpr inner-iterator& operator++();
4464
  ```
4465
 
4466
  *Effects:* Equivalent to:
@@ -4517,13 +6326,264 @@ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y
4517
  ```
4518
 
4519
  *Effects:* Equivalent to
4520
  `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
4521
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4522
  ### Counted view <a id="range.counted">[[range.counted]]</a>
4523
 
4524
- A counted view presents a `view` of the elements of the counted range
4525
  [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
4526
  non-negative integer `n`.
4527
 
4528
  The name `views::counted` denotes a customization point object
4529
  [[customization.point.object]]. Let `E` and `F` be expressions, let `T`
@@ -4536,22 +6596,22 @@ be `decay_t<decltype((E))>`, and let `D` be `iter_difference_t<T>`. If
4536
  instantiation. — *end note*]
4537
 
4538
  Otherwise, `views::counted(E, F)` is expression-equivalent to:
4539
 
4540
  - If `T` models `contiguous_iterator`, then
4541
- `span{to_address(E), static_cast<D>(F)}`.
4542
  - Otherwise, if `T` models `random_access_iterator`, then
4543
- `subrange{E, E + static_cast<D>(F)}`, except that `E` is evaluated
4544
  only once.
4545
- - Otherwise, `subrange{counted_iterator{E, F}, default_sentinel}`.
4546
 
4547
  ### Common view <a id="range.common">[[range.common]]</a>
4548
 
4549
  #### Overview <a id="range.common.overview">[[range.common.overview]]</a>
4550
 
4551
- `common_view` takes a `view` which has different types for its iterator
4552
- and sentinel and turns it into a `view` of the same elements with an
4553
  iterator and sentinel of the same type.
4554
 
4555
  [*Note 1*: `common_view` is useful for calling legacy algorithms that
4556
  expect a range’s iterator and sentinel types to be the
4557
  same. — *end note*]
@@ -4571,11 +6631,11 @@ The name `views::common` denotes a range adaptor object
4571
  template<class ForwardIterator>
4572
  size_t count(ForwardIterator first, ForwardIterator last);
4573
 
4574
  template<forward_range R>
4575
  void my_algo(R&& r) {
4576
- auto&& common = common_view{r};
4577
  auto cnt = count(common.begin(), common.end());
4578
  // ...
4579
  }
4580
  ```
4581
 
@@ -4588,19 +6648,16 @@ namespace std::ranges {
4588
  template<view V>
4589
  requires (!common_range<V> && copyable<iterator_t<V>>)
4590
  class common_view : public view_interface<common_view<V>> {
4591
  private:
4592
  V base_ = V(); // exposition only
 
4593
  public:
4594
- common_view() = default;
4595
 
4596
  constexpr explicit common_view(V r);
4597
 
4598
- template<viewable_range R>
4599
- requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
4600
- constexpr explicit common_view(R&& r);
4601
-
4602
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4603
  constexpr V base() && { return std::move(base_); }
4604
 
4605
  constexpr auto begin() {
4606
  if constexpr (random_access_range<V> && sized_range<V>)
@@ -4616,18 +6673,18 @@ namespace std::ranges {
4616
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
4617
  }
4618
 
4619
  constexpr auto end() {
4620
  if constexpr (random_access_range<V> && sized_range<V>)
4621
- return ranges::begin(base_) + ranges::size(base_);
4622
  else
4623
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
4624
  }
4625
 
4626
  constexpr auto end() const requires range<const V> {
4627
  if constexpr (random_access_range<const V> && sized_range<const V>)
4628
- return ranges::begin(base_) + ranges::size(base_);
4629
  else
4630
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
4631
  }
4632
 
4633
  constexpr auto size() requires sized_range<V> {
@@ -4647,37 +6704,26 @@ namespace std::ranges {
4647
  constexpr explicit common_view(V base);
4648
  ```
4649
 
4650
  *Effects:* Initializes *base\_* with `std::move(base)`.
4651
 
4652
- ``` cpp
4653
- template<viewable_range R>
4654
- requires (!common_range<R> && constructible_from<V, views::all_t<R>>)
4655
- constexpr explicit common_view(R&& r);
4656
- ```
4657
-
4658
- *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`.
4659
-
4660
  ### Reverse view <a id="range.reverse">[[range.reverse]]</a>
4661
 
4662
  #### Overview <a id="range.reverse.overview">[[range.reverse.overview]]</a>
4663
 
4664
- `reverse_view` takes a bidirectional `view` and produces another `view`
4665
- that iterates the same elements in reverse order.
4666
 
4667
  The name `views::reverse` denotes a range adaptor object
4668
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
4669
  `views::reverse(E)` is expression-equivalent to:
4670
 
4671
  - If the type of `E` is a (possibly cv-qualified) specialization of
4672
  `reverse_view`, equivalent to `E.base()`.
4673
- - Otherwise, if the type of `E` is cv-qualified
4674
- ``` cpp
4675
- subrange<reverse_iterator<I>, reverse_iterator<I>, K>
4676
- ```
4677
-
4678
- for some iterator type `I` and value `K` of type `subrange_kind`,
4679
  - if `K` is `subrange_kind::sized`, equivalent to:
4680
  ``` cpp
4681
  subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
4682
  ```
4683
  - otherwise, equivalent to:
@@ -4690,13 +6736,12 @@ The name `views::reverse` denotes a range adaptor object
4690
 
4691
  [*Example 1*:
4692
 
4693
  ``` cpp
4694
  vector<int> is {0,1,2,3,4};
4695
- reverse_view rv {is};
4696
- for (int i : rv)
4697
- cout << i << ' '; // prints: 4 3 2 1 0
4698
  ```
4699
 
4700
  — *end example*]
4701
 
4702
  #### Class template `reverse_view` <a id="range.reverse.view">[[range.reverse.view]]</a>
@@ -4706,12 +6751,13 @@ namespace std::ranges {
4706
  template<view V>
4707
  requires bidirectional_range<V>
4708
  class reverse_view : public view_interface<reverse_view<V>> {
4709
  private:
4710
  V base_ = V(); // exposition only
 
4711
  public:
4712
- reverse_view() = default;
4713
 
4714
  constexpr explicit reverse_view(V r);
4715
 
4716
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4717
  constexpr V base() && { return std::move(base_); }
@@ -4724,10 +6770,11 @@ namespace std::ranges {
4724
  constexpr auto end() const requires common_range<const V>;
4725
 
4726
  constexpr auto size() requires sized_range<V> {
4727
  return ranges::size(base_);
4728
  }
 
4729
  constexpr auto size() const requires sized_range<const V> {
4730
  return ranges::size(base_);
4731
  }
4732
  };
4733
 
@@ -4760,27 +6807,101 @@ the `reverse_view` for use on subsequent calls.
4760
  constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
4761
  constexpr auto begin() const requires common_range<const V>;
4762
  ```
4763
 
4764
  *Effects:* Equivalent to:
4765
- `return make_reverse_iterator(ranges::end(base_));`
4766
 
4767
  ``` cpp
4768
  constexpr reverse_iterator<iterator_t<V>> end();
4769
  constexpr auto end() const requires common_range<const V>;
4770
  ```
4771
 
4772
  *Effects:* Equivalent to:
4773
- `return make_reverse_iterator(ranges::begin(base_));`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4774
 
4775
  ### Elements view <a id="range.elements">[[range.elements]]</a>
4776
 
4777
  #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
4778
 
4779
- `elements_view` takes a `view` of tuple-like values and a `size_t`, and
4780
- produces a `view` with a value-type of the Nᵗʰ element of the adapted
4781
- `view`’s value-type.
4782
 
4783
  The name `views::elements<N>` denotes a range adaptor object
4784
  [[range.adaptor.object]]. Given a subexpression `E` and constant
4785
  expression `N`, the expression `views::elements<N>(E)` is
4786
  expression-equivalent to
@@ -4788,11 +6909,11 @@ expression-equivalent to
4788
 
4789
  [*Example 1*:
4790
 
4791
  ``` cpp
4792
  auto historical_figures = map{
4793
- {"Lovelace"sv, 1815},
4794
  {"Turing"sv, 1912},
4795
  {"Babbage"sv, 1791},
4796
  {"Hamilton"sv, 1936}
4797
  };
4798
 
@@ -4807,71 +6928,70 @@ for (auto&& born : birth_years) {
4807
  }
4808
  ```
4809
 
4810
  — *end example*]
4811
 
4812
- `keys_view` is an alias for `elements_view<views::all_t<R>, 0>`, and is
4813
- useful for extracting keys from associative containers.
4814
 
4815
  [*Example 2*:
4816
 
4817
  ``` cpp
4818
- auto names = keys_view{historical_figures};
4819
  for (auto&& name : names) {
4820
  cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
4821
  }
4822
  ```
4823
 
4824
  — *end example*]
4825
 
4826
- `values_view` is an alias for `elements_view<views::all_t<R>, 1>`, and
4827
- is useful for extracting values from associative containers.
4828
 
4829
  [*Example 3*:
4830
 
4831
  ``` cpp
4832
  auto is_even = [](const auto x) { return x % 2 == 0; };
4833
- cout << ranges::count_if(values_view{historical_figures}, is_even); // prints 2
4834
  ```
4835
 
4836
  — *end example*]
4837
 
4838
  #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
4839
 
4840
  ``` cpp
4841
  namespace std::ranges {
4842
  template<class T, size_t N>
4843
  concept has-tuple-element = // exposition only
4844
- requires(T t) {
4845
- typename tuple_size<T>::type;
4846
- requires N < tuple_size_v<T>;
4847
- typename tuple_element_t<N, T>;
4848
- { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
4849
- };
4850
 
 
 
 
4851
 
4852
  template<input_range V, size_t N>
4853
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
4854
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
4855
  class elements_view : public view_interface<elements_view<V, N>> {
4856
  public:
4857
- elements_view() = default;
4858
  constexpr explicit elements_view(V base);
4859
 
4860
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4861
  constexpr V base() && { return std::move(base_); }
4862
 
4863
  constexpr auto begin() requires (!simple-view<V>)
4864
  { return iterator<false>(ranges::begin(base_)); }
4865
 
4866
- constexpr auto begin() const requires simple-view<V>
4867
  { return iterator<true>(ranges::begin(base_)); }
4868
 
4869
- constexpr auto end()
4870
  { return sentinel<false>{ranges::end(base_)}; }
4871
 
4872
- constexpr auto end() requires common_range<V>
4873
  { return iterator<false>{ranges::end(base_)}; }
4874
 
4875
  constexpr auto end() const requires range<const V>
4876
  { return sentinel<true>{ranges::end(base_)}; }
4877
 
@@ -4884,13 +7004,15 @@ namespace std::ranges {
4884
  constexpr auto size() const requires sized_range<const V>
4885
  { return ranges::size(base_); }
4886
 
4887
  private:
4888
  // [range.elements.iterator], class template elements_view::iterator
4889
- template<bool> struct iterator; // exposition only
 
4890
  // [range.elements.sentinel], class template elements_view::sentinel
4891
- template<bool> struct sentinel; // exposition only
 
4892
  V base_ = V(); // exposition only
4893
  };
4894
  }
4895
  ```
4896
 
@@ -4904,35 +7026,39 @@ constexpr explicit elements_view(V base);
4904
 
4905
  ``` cpp
4906
  namespace std::ranges {
4907
  template<input_range V, size_t N>
4908
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
4909
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
4910
  template<bool Const>
4911
- class elements_view<V, N>::iterator { // exposition only
4912
- using Base = conditional_t<Const, const V, V>; // exposition only
 
 
 
 
4913
 
4914
- iterator_t<Base> current_ = iterator_t<Base>();
4915
  public:
4916
- using iterator_category = typename iterator_traits<iterator_t<Base>>::iterator_category;
 
4917
  using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
4918
  using difference_type = range_difference_t<Base>;
4919
 
4920
- iterator() = default;
4921
  constexpr explicit iterator(iterator_t<Base> current);
4922
  constexpr iterator(iterator<!Const> i)
4923
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
4924
 
4925
- constexpr iterator_t<Base> base() const&
4926
- requires copyable<iterator_t<Base>>;
4927
  constexpr iterator_t<Base> base() &&;
4928
 
4929
  constexpr decltype(auto) operator*() const
4930
- { return get<N>(*current_); }
4931
 
4932
  constexpr iterator& operator++();
4933
- constexpr void operator++(int) requires (!forward_range<Base>);
4934
  constexpr iterator operator++(int) requires forward_range<Base>;
4935
 
4936
  constexpr iterator& operator--() requires bidirectional_range<Base>;
4937
  constexpr iterator operator--(int) requires bidirectional_range<Base>;
4938
 
@@ -4941,20 +7067,20 @@ namespace std::ranges {
4941
  constexpr iterator& operator-=(difference_type x)
4942
  requires random_access_range<Base>;
4943
 
4944
  constexpr decltype(auto) operator[](difference_type n) const
4945
  requires random_access_range<Base>
4946
- { return get<N>(*(current_ + n)); }
4947
 
4948
  friend constexpr bool operator==(const iterator& x, const iterator& y)
4949
  requires equality_comparable<iterator_t<Base>>;
4950
 
4951
  friend constexpr bool operator<(const iterator& x, const iterator& y)
4952
  requires random_access_range<Base>;
4953
  friend constexpr bool operator>(const iterator& x, const iterator& y)
4954
  requires random_access_range<Base>;
4955
- friend constexpr bool operator<=(const iterator& y, const iterator& y)
4956
  requires random_access_range<Base>;
4957
  friend constexpr bool operator>=(const iterator& x, const iterator& y)
4958
  requires random_access_range<Base>;
4959
  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
4960
  requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
@@ -4964,15 +7090,51 @@ namespace std::ranges {
4964
  friend constexpr iterator operator+(difference_type x, const iterator& y)
4965
  requires random_access_range<Base>;
4966
  friend constexpr iterator operator-(const iterator& x, difference_type y)
4967
  requires random_access_range<Base>;
4968
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4969
- requires random_access_range<Base>;
4970
  };
4971
  }
4972
  ```
4973
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4974
  ``` cpp
4975
  constexpr explicit iterator(iterator_t<Base> current);
4976
  ```
4977
 
4978
  *Effects:* Initializes *current\_* with `std::move(current)`.
@@ -4983,12 +7145,11 @@ constexpr iterator(iterator<!Const> i)
4983
  ```
4984
 
4985
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
4986
 
4987
  ``` cpp
4988
- constexpr iterator_t<Base> base() const&
4989
- requires copyable<iterator_t<Base>>;
4990
  ```
4991
 
4992
  *Effects:* Equivalent to: `return `*`current_`*`;`
4993
 
4994
  ``` cpp
@@ -5007,11 +7168,11 @@ constexpr iterator& operator++();
5007
  ++current_;
5008
  return *this;
5009
  ```
5010
 
5011
  ``` cpp
5012
- constexpr void operator++(int) requires (!forward_range<Base>);
5013
  ```
5014
 
5015
  *Effects:* Equivalent to: `++`*`current_`*.
5016
 
5017
  ``` cpp
@@ -5048,11 +7209,11 @@ auto temp = *this;
5048
  --current_;
5049
  return temp;
5050
  ```
5051
 
5052
  ``` cpp
5053
- constexpr iterator& operator+=(difference_type n);
5054
  requires random_access_range<Base>;
5055
  ```
5056
 
5057
  *Effects:* Equivalent to:
5058
 
@@ -5119,62 +7280,68 @@ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
5119
  ``` cpp
5120
  friend constexpr iterator operator+(const iterator& x, difference_type y)
5121
  requires random_access_range<Base>;
5122
  ```
5123
 
5124
- *Effects:* Equivalent to: `return iterator{x} += y;`
5125
 
5126
  ``` cpp
5127
  friend constexpr iterator operator+(difference_type x, const iterator& y)
5128
  requires random_access_range<Base>;
5129
  ```
5130
 
5131
  *Effects:* Equivalent to: `return y + x;`
5132
 
5133
  ``` cpp
5134
- constexpr iterator operator-(const iterator& x, difference_type y)
5135
  requires random_access_range<Base>;
5136
  ```
5137
 
5138
- *Effects:* Equivalent to: `return iterator{x} -= y;`
5139
 
5140
  ``` cpp
5141
- constexpr difference_type operator-(const iterator& x, const iterator& y)
5142
- requires random_access_range<Base>;
5143
  ```
5144
 
5145
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
5146
 
5147
  #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
5148
 
5149
  ``` cpp
5150
  namespace std::ranges {
5151
  template<input_range V, size_t N>
5152
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
5153
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
5154
  template<bool Const>
5155
- class elements_view<V, N>::sentinel { // exposition only
5156
  private:
5157
- using Base = conditional_t<Const, const V, V>; // exposition only
5158
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
5159
  public:
5160
  sentinel() = default;
5161
  constexpr explicit sentinel(sentinel_t<Base> end);
5162
  constexpr sentinel(sentinel<!Const> other)
5163
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
5164
 
5165
  constexpr sentinel_t<Base> base() const;
5166
 
5167
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
5168
 
5169
- friend constexpr range_difference_t<Base>
5170
- operator-(const iterator<Const>& x, const sentinel& y)
5171
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
5172
 
5173
- friend constexpr range_difference_t<Base>
5174
- operator-(const sentinel& x, const iterator<Const>& y)
5175
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
5176
  };
5177
  }
5178
  ```
5179
 
5180
  ``` cpp
@@ -5195,40 +7362,5345 @@ constexpr sentinel_t<Base> base() const;
5195
  ```
5196
 
5197
  *Effects:* Equivalent to: `return `*`end_`*`;`
5198
 
5199
  ``` cpp
5200
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
5201
  ```
5202
 
5203
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
5204
 
5205
  ``` cpp
5206
- friend constexpr range_difference_t<Base>
5207
- operator-(const iterator<Const>& x, const sentinel& y)
5208
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
5209
  ```
5210
 
5211
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
5212
 
5213
  ``` cpp
5214
- friend constexpr range_difference_t<Base>
5215
- operator-(const sentinel& x, const iterator<Const>& y)
5216
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5217
  ```
5218
 
5219
  *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
5220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5221
  <!-- Link reference definitions -->
5222
- [basic.compound]: basic.md#basic.compound
5223
  [concepts.equality]: concepts.md#concepts.equality
5224
  [containers]: containers.md#containers
5225
  [conv.rval]: expr.md#conv.rval
 
 
 
 
 
 
5226
  [customization.point.object]: library.md#customization.point.object
5227
- [dcl.array]: dcl.md#dcl.array
 
 
5228
  [expr.const]: expr.md#expr.const
 
 
5229
  [iterator.concept.bidir]: iterators.md#iterator.concept.bidir
 
5230
  [iterator.concept.iterator]: iterators.md#iterator.concept.iterator
5231
  [iterator.concept.output]: iterators.md#iterator.concept.output
5232
  [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
5233
  [iterator.concept.sizedsentinel]: iterators.md#iterator.concept.sizedsentinel
5234
  [iterator.concept.winc]: iterators.md#iterator.concept.winc
@@ -5239,15 +12711,51 @@ friend constexpr range_difference_t<Base>
5239
  [range.access.cbegin]: #range.access.cbegin
5240
  [range.access.cend]: #range.access.cend
5241
  [range.access.crbegin]: #range.access.crbegin
5242
  [range.access.crend]: #range.access.crend
5243
  [range.access.end]: #range.access.end
 
5244
  [range.access.rbegin]: #range.access.rbegin
5245
  [range.access.rend]: #range.access.rend
 
5246
  [range.adaptor.object]: #range.adaptor.object
5247
  [range.adaptors]: #range.adaptors
 
 
 
 
 
 
 
 
 
 
 
5248
  [range.all]: #range.all
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5249
  [range.common]: #range.common
5250
  [range.common.overview]: #range.common.overview
5251
  [range.common.view]: #range.common.view
5252
  [range.counted]: #range.counted
5253
  [range.dangling]: #range.dangling
@@ -5260,14 +12768,21 @@ friend constexpr range_difference_t<Base>
5260
  [range.elements]: #range.elements
5261
  [range.elements.iterator]: #range.elements.iterator
5262
  [range.elements.overview]: #range.elements.overview
5263
  [range.elements.sentinel]: #range.elements.sentinel
5264
  [range.elements.view]: #range.elements.view
 
5265
  [range.empty]: #range.empty
5266
  [range.empty.overview]: #range.empty.overview
5267
  [range.empty.view]: #range.empty.view
 
 
 
 
 
5268
  [range.factories]: #range.factories
 
5269
  [range.filter]: #range.filter
5270
  [range.filter.iterator]: #range.filter.iterator
5271
  [range.filter.overview]: #range.filter.overview
5272
  [range.filter.sentinel]: #range.filter.sentinel
5273
  [range.filter.view]: #range.filter.view
@@ -5283,37 +12798,63 @@ friend constexpr range_difference_t<Base>
5283
  [range.join]: #range.join
5284
  [range.join.iterator]: #range.join.iterator
5285
  [range.join.overview]: #range.join.overview
5286
  [range.join.sentinel]: #range.join.sentinel
5287
  [range.join.view]: #range.join.view
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5288
  [range.prim.cdata]: #range.prim.cdata
5289
  [range.prim.data]: #range.prim.data
5290
  [range.prim.empty]: #range.prim.empty
5291
  [range.prim.size]: #range.prim.size
5292
  [range.prim.ssize]: #range.prim.ssize
5293
  [range.range]: #range.range
5294
  [range.ref.view]: #range.ref.view
5295
  [range.refinements]: #range.refinements
 
 
 
 
5296
  [range.req]: #range.req
5297
  [range.req.general]: #range.req.general
5298
  [range.reverse]: #range.reverse
5299
  [range.reverse.overview]: #range.reverse.overview
5300
  [range.reverse.view]: #range.reverse.view
5301
- [range.semi.wrap]: #range.semi.wrap
5302
  [range.single]: #range.single
5303
  [range.single.overview]: #range.single.overview
5304
  [range.single.view]: #range.single.view
5305
  [range.sized]: #range.sized
 
 
 
 
 
5306
  [range.split]: #range.split
5307
- [range.split.inner]: #range.split.inner
5308
- [range.split.outer]: #range.split.outer
5309
- [range.split.outer.value]: #range.split.outer.value
5310
  [range.split.overview]: #range.split.overview
 
5311
  [range.split.view]: #range.split.view
 
 
 
 
5312
  [range.subrange]: #range.subrange
5313
  [range.subrange.access]: #range.subrange.access
5314
  [range.subrange.ctor]: #range.subrange.ctor
 
5315
  [range.summary]: #range.summary
5316
  [range.take]: #range.take
5317
  [range.take.overview]: #range.take.overview
5318
  [range.take.sentinel]: #range.take.sentinel
5319
  [range.take.view]: #range.take.view
@@ -5325,14 +12866,32 @@ friend constexpr range_difference_t<Base>
5325
  [range.transform.iterator]: #range.transform.iterator
5326
  [range.transform.overview]: #range.transform.overview
5327
  [range.transform.sentinel]: #range.transform.sentinel
5328
  [range.transform.view]: #range.transform.view
5329
  [range.utility]: #range.utility
 
 
 
 
 
5330
  [range.utility.helpers]: #range.utility.helpers
5331
  [range.view]: #range.view
 
 
 
 
 
 
 
 
 
 
5332
  [ranges]: #ranges
5333
  [ranges.general]: #ranges.general
5334
  [ranges.syn]: #ranges.syn
5335
  [string.view]: strings.md#string.view
 
 
5336
  [view.interface]: #view.interface
 
5337
  [view.interface.members]: #view.interface.members
5338
  [views.span]: containers.md#views.span
 
1
  # Ranges library <a id="ranges">[[ranges]]</a>
2
 
3
  ## General <a id="ranges.general">[[ranges.general]]</a>
4
 
5
+ This Clause describes components for dealing with ranges of elements.
6
 
7
  The following subclauses describe range and view requirements, and
8
+ components for range primitives and range generators as summarized in
9
+ [[range.summary]].
10
 
11
  **Table: Ranges library summary** <a id="range.summary">[range.summary]</a>
12
 
13
  | Subclause | | Header |
14
+ | ------------------- | ---------------- | ------------- |
15
  | [[range.access]] | Range access | `<ranges>` |
16
  | [[range.req]] | Requirements | |
17
  | [[range.utility]] | Range utilities | |
18
  | [[range.factories]] | Range factories | |
19
  | [[range.adaptors]] | Range adaptors | |
20
+ | [[coro.generator]] | Range generators | `<generator>` |
21
 
22
 
23
  ## Header `<ranges>` synopsis <a id="ranges.syn">[[ranges.syn]]</a>
24
 
25
  ``` cpp
 
28
  #include <iterator> // see [iterator.synopsis]
29
 
30
  namespace std::ranges {
31
  inline namespace unspecified {
32
  // [range.access], range access
33
+ inline constexpr unspecified begin = unspecified; // freestanding
34
+ inline constexpr unspecified end = unspecified; // freestanding
35
+ inline constexpr unspecified cbegin = unspecified; // freestanding
36
+ inline constexpr unspecified cend = unspecified; // freestanding
37
+ inline constexpr unspecified rbegin = unspecified; // freestanding
38
+ inline constexpr unspecified rend = unspecified; // freestanding
39
+ inline constexpr unspecified crbegin = unspecified; // freestanding
40
+ inline constexpr unspecified crend = unspecified; // freestanding
41
 
42
+ inline constexpr unspecified size = unspecified; // freestanding
43
+ inline constexpr unspecified ssize = unspecified; // freestanding
44
+ inline constexpr unspecified empty = unspecified; // freestanding
45
+ inline constexpr unspecified data = unspecified; // freestanding
46
+ inline constexpr unspecified cdata = unspecified; // freestanding
47
  }
48
 
49
  // [range.range], ranges
50
  template<class T>
51
+ concept range = see below; // freestanding
52
 
53
  template<class T>
54
+ constexpr bool enable_borrowed_range = false; // freestanding
55
 
56
  template<class T>
57
+ concept borrowed_range = see below; // freestanding
58
 
59
  template<class T>
60
+ using iterator_t = decltype(ranges::begin(declval<T&>())); // freestanding
61
  template<range R>
62
+ using sentinel_t = decltype(ranges::end(declval<R&>())); // freestanding
63
  template<range R>
64
+ using const_iterator_t = const_iterator<iterator_t<R>>; // freestanding
65
+ template<range R>
66
+ using const_sentinel_t = const_sentinel<sentinel_t<R>>; // freestanding
67
+ template<range R>
68
+ using range_difference_t = iter_difference_t<iterator_t<R>>; // freestanding
69
  template<sized_range R>
70
+ using range_size_t = decltype(ranges::size(declval<R&>())); // freestanding
71
  template<range R>
72
+ using range_value_t = iter_value_t<iterator_t<R>>; // freestanding
73
  template<range R>
74
+ using range_reference_t = iter_reference_t<iterator_t<R>>; // freestanding
75
  template<range R>
76
+ using range_const_reference_t = iter_const_reference_t<iterator_t<R>>; // freestanding
77
+ template<range R>
78
+ using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>; // freestanding
79
+ template<range R>
80
+ using range_common_reference_t = iter_common_reference_t<iterator_t<R>>; // freestanding
81
 
82
  // [range.sized], sized ranges
83
  template<class>
84
+ constexpr bool disable_sized_range = false; // freestanding
85
 
86
  template<class T>
87
+ concept sized_range = see below; // freestanding
88
 
89
  // [range.view], views
90
  template<class T>
91
+ constexpr bool enable_view = see below; // freestanding
92
 
93
+ struct view_base {}; // freestanding
94
 
95
  template<class T>
96
+ concept view = see below; // freestanding
97
 
98
  // [range.refinements], other range refinements
99
  template<class R, class T>
100
+ concept output_range = see below; // freestanding
101
 
102
  template<class T>
103
+ concept input_range = see below; // freestanding
104
 
105
  template<class T>
106
+ concept forward_range = see below; // freestanding
107
 
108
  template<class T>
109
+ concept bidirectional_range = see below; // freestanding
110
 
111
  template<class T>
112
+ concept random_access_range = see below; // freestanding
113
 
114
  template<class T>
115
+ concept contiguous_range = see below; // freestanding
116
 
117
  template<class T>
118
+ concept common_range = see below; // freestanding
119
 
120
  template<class T>
121
+ concept viewable_range = see below; // freestanding
122
+
123
+ template<class T>
124
+ concept constant_range = see below; // freestanding
125
 
126
  // [view.interface], class template view_interface
127
  template<class D>
128
  requires is_class_v<D> && same_as<D, remove_cv_t<D>>
129
+ class view_interface; // freestanding
130
 
131
  // [range.subrange], sub-ranges
132
+ enum class subrange_kind : bool { unsized, sized }; // freestanding
133
 
134
  template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K = see below>
135
  requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
136
+ class subrange; // freestanding
137
 
138
+ template<class I, class S, subrange_kind K>
139
+ constexpr bool enable_borrowed_range<subrange<I, S, K>> = true; // freestanding
140
 
141
+ template<size_t N, class I, class S, subrange_kind K>
142
+ requires ((N == 0 && copyable<I>) || N == 1)
143
+ constexpr auto get(const subrange<I, S, K>& r); // freestanding
144
+
145
+ template<size_t N, class I, class S, subrange_kind K>
146
+ requires (N < 2)
147
+ constexpr auto get(subrange<I, S, K>&& r); // freestanding
148
+ }
149
+
150
+ namespace std {
151
+ using ranges::get; // freestanding
152
+ }
153
+
154
+ namespace std::ranges {
155
  // [range.dangling], dangling iterator handling
156
+ struct dangling; // freestanding
157
+
158
+ // [range.elementsof], class template elements_of
159
+ template<range R, class Allocator = allocator<byte>>
160
+ struct elements_of;
161
 
162
  template<range R>
163
+ using borrowed_iterator_t = see below; // freestanding
164
 
165
  template<range R>
166
+ using borrowed_subrange_t = see below; // freestanding
167
+
168
+ // [range.utility.conv], range conversions
169
+ template<class C, input_range R, class... Args> requires (!view<C>)
170
+ constexpr C to(R&& r, Args&&... args); // freestanding
171
+ template<template<class...> class C, input_range R, class... Args>
172
+ constexpr auto to(R&& r, Args&&... args); // freestanding
173
+ template<class C, class... Args> requires (!view<C>)
174
+ constexpr auto to(Args&&... args); // freestanding
175
+ template<template<class...> class C, class... Args>
176
+ constexpr auto to(Args&&... args); // freestanding
177
 
178
  // [range.empty], empty view
179
  template<class T>
180
  requires is_object_v<T>
181
+ class empty_view; // freestanding
182
 
183
  template<class T>
184
+ constexpr bool enable_borrowed_range<empty_view<T>> = true; // freestanding
185
 
186
  namespace views {
187
  template<class T>
188
+ constexpr empty_view<T> empty{}; // freestanding
189
  }
190
 
191
  // [range.single], single view
192
+ template<move_constructible T>
193
  requires is_object_v<T>
194
+ class single_view; // freestanding
195
 
196
+ namespace views { inline constexpr unspecified single = unspecified; } // freestanding
197
+
198
+ template<bool Const, class T>
199
+ using maybe-const = conditional_t<Const, const T, T>; // exposition only
200
 
201
  // [range.iota], iota view
202
  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
203
+ requires weakly-equality-comparable-with<W, Bound> && copyable<W>
204
+ class iota_view; // freestanding
205
 
206
+ template<class W, class Bound>
207
+ constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true; // freestanding
208
 
209
+ namespace views { inline constexpr unspecified iota = unspecified; } // freestanding
210
+
211
+ // [range.repeat], repeat view
212
+ template<move_constructible T, semiregular Bound = unreachable_sentinel_t>
213
+ requires see below
214
+ class repeat_view; // freestanding
215
+
216
+ namespace views { inline constexpr unspecified repeat = unspecified; } // freestanding
217
 
218
  // [range.istream], istream view
219
  template<movable Val, class CharT, class Traits = char_traits<CharT>>
220
  requires see below
221
  class basic_istream_view;
222
+ template<class Val>
223
+ using istream_view = basic_istream_view<Val, char>;
224
+ template<class Val>
225
+ using wistream_view = basic_istream_view<Val, wchar_t>;
226
+
227
+ namespace views { template<class T> constexpr unspecified istream = unspecified; }
228
+
229
+ // [range.adaptor.object], range adaptor objects
230
+ template<class D>
231
+ requires is_class_v<D> && same_as<D, remove_cv_t<D>>
232
+ class range_adaptor_closure { }; // freestanding
233
 
234
  // [range.all], all view
235
  namespace views {
236
+ inline constexpr unspecified all = unspecified; // freestanding
237
 
238
  template<viewable_range R>
239
+ using all_t = decltype(all(declval<R>())); // freestanding
240
  }
241
 
242
+ // [range.ref.view], ref view
243
  template<range R>
244
  requires is_object_v<R>
245
+ class ref_view; // freestanding
246
 
247
  template<class T>
248
+ constexpr bool enable_borrowed_range<ref_view<T>> = true; // freestanding
249
+
250
+ // [range.owning.view], owning view
251
+ template<range R>
252
+ requires see below
253
+ class owning_view; // freestanding
254
+
255
+ template<class T>
256
+ constexpr bool enable_borrowed_range<owning_view<T>> = // freestanding
257
+ enable_borrowed_range<T>;
258
+
259
+ // [range.as.rvalue], as rvalue view
260
+ template<view V>
261
+ requires input_range<V>
262
+ class as_rvalue_view; // freestanding
263
+
264
+ template<class T>
265
+ constexpr bool enable_borrowed_range<as_rvalue_view<T>> = // freestanding
266
+ enable_borrowed_range<T>;
267
+
268
+ namespace views { inline constexpr unspecified as_rvalue = unspecified; } // freestanding
269
 
270
  // [range.filter], filter view
271
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
272
  requires view<V> && is_object_v<Pred>
273
+ class filter_view; // freestanding
274
 
275
+ namespace views { inline constexpr unspecified filter = unspecified; } // freestanding
276
 
277
  // [range.transform], transform view
278
+ template<input_range V, move_constructible F>
279
  requires view<V> && is_object_v<F> &&
280
+ regular_invocable<F&, range_reference_t<V>> &&
281
+ can-reference<invoke_result_t<F&, range_reference_t<V>>>
282
+ class transform_view; // freestanding
283
 
284
+ namespace views { inline constexpr unspecified transform = unspecified; } // freestanding
285
 
286
  // [range.take], take view
287
+ template<view> class take_view; // freestanding
288
 
289
+ template<class T>
290
+ constexpr bool enable_borrowed_range<take_view<T>> = // freestanding
291
+ enable_borrowed_range<T>;
292
+
293
+ namespace views { inline constexpr unspecified take = unspecified; } // freestanding
294
 
295
  // [range.take.while], take while view
296
  template<view V, class Pred>
297
  requires input_range<V> && is_object_v<Pred> &&
298
  indirect_unary_predicate<const Pred, iterator_t<V>>
299
+ class take_while_view; // freestanding
300
 
301
+ namespace views { inline constexpr unspecified take_while = unspecified; } // freestanding
302
 
303
  // [range.drop], drop view
304
  template<view V>
305
+ class drop_view; // freestanding
306
 
307
+ template<class T>
308
+ constexpr bool enable_borrowed_range<drop_view<T>> = // freestanding
309
+ enable_borrowed_range<T>;
310
+
311
+ namespace views { inline constexpr unspecified drop = unspecified; } // freestanding
312
 
313
  // [range.drop.while], drop while view
314
  template<view V, class Pred>
315
  requires input_range<V> && is_object_v<Pred> &&
316
  indirect_unary_predicate<const Pred, iterator_t<V>>
317
+ class drop_while_view; // freestanding
318
 
319
+ template<class T, class Pred>
320
+ constexpr bool enable_borrowed_range<drop_while_view<T, Pred>> = // freestanding
321
+ enable_borrowed_range<T>;
322
+
323
+ namespace views { inline constexpr unspecified drop_while = unspecified; } // freestanding
324
 
325
  // [range.join], join view
326
  template<input_range V>
327
+ requires view<V> && input_range<range_reference_t<V>>
328
+ class join_view; // freestanding
 
 
329
 
330
+ namespace views { inline constexpr unspecified join = unspecified; } // freestanding
331
 
332
+ // [range.join.with], join with view
333
+ template<class R, class P>
334
+ concept compatible-joinable-ranges = see below; // exposition only
335
+
336
+ template<input_range V, forward_range Pattern>
337
+ requires view<V> && input_range<range_reference_t<V>>
338
+ && view<Pattern>
339
+ && compatible-joinable-ranges<range_reference_t<V>, Pattern>
340
+ class join_with_view; // freestanding
341
+
342
+ namespace views { inline constexpr unspecified join_with = unspecified; } // freestanding
343
+
344
+ // [range.lazy.split], lazy split view
345
  template<class R>
346
  concept tiny-range = see below; // exposition only
347
 
348
  template<input_range V, forward_range Pattern>
349
  requires view<V> && view<Pattern> &&
350
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
351
  (forward_range<V> || tiny-range<Pattern>)
352
+ class lazy_split_view; // freestanding
353
 
354
+ // [range.split], split view
355
+ template<forward_range V, forward_range Pattern>
356
+ requires view<V> && view<Pattern> &&
357
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
358
+ class split_view; // freestanding
359
+
360
+ namespace views {
361
+ inline constexpr unspecified lazy_split = unspecified; // freestanding
362
+ inline constexpr unspecified split = unspecified; // freestanding
363
+ }
364
 
365
  // [range.counted], counted view
366
+ namespace views { inline constexpr unspecified counted = unspecified; } // freestanding
367
 
368
  // [range.common], common view
369
  template<view V>
370
  requires (!common_range<V> && copyable<iterator_t<V>>)
371
+ class common_view; // freestanding
372
 
373
+ template<class T>
374
+ constexpr bool enable_borrowed_range<common_view<T>> = // freestanding
375
+ enable_borrowed_range<T>;
376
+
377
+ namespace views { inline constexpr unspecified common = unspecified; } // freestanding
378
 
379
  // [range.reverse], reverse view
380
  template<view V>
381
  requires bidirectional_range<V>
382
+ class reverse_view; // freestanding
383
 
384
+ template<class T>
385
+ constexpr bool enable_borrowed_range<reverse_view<T>> = // freestanding
386
+ enable_borrowed_range<T>;
387
+
388
+ namespace views { inline constexpr unspecified reverse = unspecified; } // freestanding
389
+
390
+ // [range.as.const], as const view
391
+ template<input_range R>
392
+ constexpr auto& possibly-const-range(R& r) { // exposition only
393
+ if constexpr (constant_range<const R> && !constant_range<R>) {
394
+ return const_cast<const R&>(r);
395
+ } else {
396
+ return r;
397
+ }
398
+ }
399
+
400
+ template<view V>
401
+ requires input_range<V>
402
+ class as_const_view; // freestanding
403
+
404
+ template<class T>
405
+ constexpr bool enable_borrowed_range<as_const_view<T>> = // freestanding
406
+ enable_borrowed_range<T>;
407
+
408
+ namespace views { inline constexpr unspecified as_const = unspecified; } // freestanding
409
 
410
  // [range.elements], elements view
411
  template<input_range V, size_t N>
412
+ requires see below
413
+ class elements_view; // freestanding
414
+
415
+ template<class T, size_t N>
416
+ constexpr bool enable_borrowed_range<elements_view<T, N>> = // freestanding
417
+ enable_borrowed_range<T>;
418
 
419
  template<class R>
420
+ using keys_view = elements_view<R, 0>; // freestanding
421
  template<class R>
422
+ using values_view = elements_view<R, 1>; // freestanding
423
+
424
+ namespace views {
425
+ template<size_t N>
426
+ constexpr unspecified elements = unspecified; // freestanding
427
+ inline constexpr auto keys = elements<0>; // freestanding
428
+ inline constexpr auto values = elements<1>; // freestanding
429
+ }
430
+
431
+ // [range.enumerate], enumerate view
432
+ template<input_range View>
433
+ requires view<View>
434
+ class enumerate_view; // freestanding
435
+
436
+ template<class View>
437
+ constexpr bool enable_borrowed_range<enumerate_view<View>> = // freestanding
438
+ enable_borrowed_range<View>;
439
+
440
+ namespace views { inline constexpr unspecified enumerate = unspecified; } // freestanding
441
+
442
+ // [range.zip], zip view
443
+ template<input_range... Views>
444
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
445
+ class zip_view; // freestanding
446
+
447
+ template<class... Views>
448
+ constexpr bool enable_borrowed_range<zip_view<Views...>> = // freestanding
449
+ (enable_borrowed_range<Views> && ...);
450
+
451
+ namespace views { inline constexpr unspecified zip = unspecified; } // freestanding
452
+
453
+ // [range.zip.transform], zip transform view
454
+ template<move_constructible F, input_range... Views>
455
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
456
+ regular_invocable<F&, range_reference_t<Views>...> &&
457
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
458
+ class zip_transform_view; // freestanding
459
+
460
+ namespace views { inline constexpr unspecified zip_transform = unspecified; } // freestanding
461
+
462
+ // [range.adjacent], adjacent view
463
+ template<forward_range V, size_t N>
464
+ requires view<V> && (N > 0)
465
+ class adjacent_view; // freestanding
466
+
467
+ template<class V, size_t N>
468
+ constexpr bool enable_borrowed_range<adjacent_view<V, N>> = // freestanding
469
+ enable_borrowed_range<V>;
470
+
471
+ namespace views {
472
+ template<size_t N>
473
+ constexpr unspecified adjacent = unspecified; // freestanding
474
+ inline constexpr auto pairwise = adjacent<2>; // freestanding
475
+ }
476
+
477
+ // [range.adjacent.transform], adjacent transform view
478
+ template<forward_range V, move_constructible F, size_t N>
479
+ requires see below
480
+ class adjacent_transform_view; // freestanding
481
 
482
  namespace views {
483
  template<size_t N>
484
+ constexpr unspecified adjacent_transform = unspecified; // freestanding
485
+ inline constexpr auto pairwise_transform = adjacent_transform<2>; // freestanding
 
486
  }
487
+
488
+ // [range.chunk], chunk view
489
+ template<view V>
490
+ requires input_range<V>
491
+ class chunk_view; // freestanding
492
+
493
+ template<view V>
494
+ requires forward_range<V>
495
+ class chunk_view<V>; // freestanding
496
+
497
+ template<class V>
498
+ constexpr bool enable_borrowed_range<chunk_view<V>> = // freestanding
499
+ forward_range<V> && enable_borrowed_range<V>;
500
+
501
+ namespace views { inline constexpr unspecified chunk = unspecified; } // freestanding
502
+
503
+ // [range.slide], slide view
504
+ template<forward_range V>
505
+ requires view<V>
506
+ class slide_view; // freestanding
507
+
508
+ template<class V>
509
+ constexpr bool enable_borrowed_range<slide_view<V>> =
510
+ enable_borrowed_range<V>; // freestanding
511
+
512
+ namespace views { inline constexpr unspecified slide = unspecified; } // freestanding
513
+
514
+ // [range.chunk.by], chunk by view
515
+ template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred>
516
+ requires view<V> && is_object_v<Pred>
517
+ class chunk_by_view; // freestanding
518
+
519
+ namespace views { inline constexpr unspecified chunk_by = unspecified; } // freestanding
520
+
521
+ // [range.stride], stride view
522
+ template<input_range V>
523
+ requires view<V>
524
+ class stride_view; // freestanding
525
+
526
+ template<class V>
527
+ constexpr bool enable_borrowed_range<stride_view<V>> = // freestanding
528
+ enable_borrowed_range<V>;
529
+
530
+ namespace views { inline constexpr unspecified stride = unspecified; } // freestanding
531
+
532
+ // [range.cartesian], cartesian product view
533
+ template<input_range First, forward_range... Vs>
534
+ requires (view<First> && ... && view<Vs>)
535
+ class cartesian_product_view; // freestanding
536
+
537
+ namespace views { inline constexpr unspecified cartesian_product = unspecified; } // freestanding
538
  }
539
 
540
  namespace std {
541
+ namespace views = ranges::views; // freestanding
542
+
543
+ template<class T> struct tuple_size; // freestanding
544
+ template<size_t I, class T> struct tuple_element; // freestanding
545
 
546
  template<class I, class S, ranges::subrange_kind K>
547
+ struct tuple_size<ranges::subrange<I, S, K>> // freestanding
548
  : integral_constant<size_t, 2> {};
549
  template<class I, class S, ranges::subrange_kind K>
550
+ struct tuple_element<0, ranges::subrange<I, S, K>> { // freestanding
551
+ using type = I; // freestanding
552
  };
553
  template<class I, class S, ranges::subrange_kind K>
554
+ struct tuple_element<1, ranges::subrange<I, S, K>> { // freestanding
555
+ using type = S; // freestanding
556
  };
557
  template<class I, class S, ranges::subrange_kind K>
558
+ struct tuple_element<0, const ranges::subrange<I, S, K>> { // freestanding
559
+ using type = I; // freestanding
560
  };
561
  template<class I, class S, ranges::subrange_kind K>
562
+ struct tuple_element<1, const ranges::subrange<I, S, K>> { // freestanding
563
+ using type = S; // freestanding
564
  };
565
+
566
+ struct from_range_t { explicit from_range_t() = default; }; // freestanding
567
+ inline constexpr from_range_t from_range{}; // freestanding
568
  }
569
  ```
570
 
571
+ Within this Clause, for an integer-like type `X`
572
  [[iterator.concept.winc]], `make-unsigned-like-t<X>` denotes
573
  `make_unsigned_t<X>` if `X` is an integer type; otherwise, it denotes a
574
  corresponding unspecified unsigned-integer-like type of the same width
575
  as `X`. For an expression `x` of type `X`, `to-unsigned-like(x)` is `x`
576
  explicitly converted to `make-unsigned-like-t<X>`.
577
 
578
+ Also within this Clause, `make-signed-like-t<X>` for an integer-like
579
+ type `X` denotes `make_signed_t<X>` if `X` is an integer type;
580
+ otherwise, it denotes a corresponding unspecified signed-integer-like
581
+ type of the same width as `X`.
582
+
583
  ## Range access <a id="range.access">[[range.access]]</a>
584
 
585
+ ### General <a id="range.access.general">[[range.access.general]]</a>
586
+
587
  In addition to being available via inclusion of the `<ranges>` header,
588
  the customization point objects in [[range.access]] are available when
589
  `<iterator>` is included.
590
 
591
+ Within [[range.access]], the *reified object* of a subexpression `E`
592
  denotes
593
 
594
  - the same object as `E` if `E` is a glvalue, or
595
  - the result of applying the temporary materialization conversion
596
  [[conv.rval]] to `E` otherwise.
 
603
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
604
  denotes the reified object for `E`. Then:
605
 
606
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
607
  `false`, `ranges::begin(E)` is ill-formed.
608
+ - Otherwise, if `T` is an array type [[term.array.type]] and
609
  `remove_all_extents_t<T>` is an incomplete type, `ranges::begin(E)` is
610
  ill-formed with no diagnostic required.
611
  - Otherwise, if `T` is an array type, `ranges::begin(E)` is
612
  expression-equivalent to `t + 0`.
613
+ - Otherwise, if `auto(t.begin())` is a valid expression whose type
614
  models `input_or_output_iterator`, `ranges::begin(E)` is
615
+ expression-equivalent to `auto(t.begin())`.
616
+ - Otherwise, if `T` is a class or enumeration type and `auto(begin(t))`
617
+ is a valid expression whose type models `input_or_output_iterator`
618
+ where the meaning of `begin` is established as-if by performing
619
+ argument-dependent lookup only [[basic.lookup.argdep]], then
620
+ `ranges::begin(E)` is expression-equivalent to that expression.
 
 
 
 
 
 
 
 
621
  - Otherwise, `ranges::begin(E)` is ill-formed.
622
 
623
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
624
  failure when `ranges::begin(E)` appears in the immediate context of a
625
  template instantiation. — *end note*]
 
635
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
636
  denotes the reified object for `E`. Then:
637
 
638
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
639
  `false`, `ranges::end(E)` is ill-formed.
640
+ - Otherwise, if `T` is an array type [[term.array.type]] and
641
  `remove_all_extents_t<T>` is an incomplete type, `ranges::end(E)` is
642
  ill-formed with no diagnostic required.
643
  - Otherwise, if `T` is an array of unknown bound, `ranges::end(E)` is
644
  ill-formed.
645
  - Otherwise, if `T` is an array, `ranges::end(E)` is
646
  expression-equivalent to `t + extent_v<T>`.
647
+ - Otherwise, if `auto(t.end())` is a valid expression whose type models
648
+ `sentinel_for<iterator_t<T>>` then `ranges::end(E)` is
649
+ expression-equivalent to `auto(t.end())`.
650
+ - Otherwise, if `T` is a class or enumeration type and `auto(end(t))` is
651
+ a valid expression whose type models `sentinel_for<iterator_t<T>>`
652
+ where the meaning of `end` is established as-if by performing
653
+ argument-dependent lookup only [[basic.lookup.argdep]], then
654
+ `ranges::end(E)` is expression-equivalent to that expression.
 
 
 
 
 
 
 
655
  - Otherwise, `ranges::end(E)` is ill-formed.
656
 
657
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
658
  failure when `ranges::end(E)` appears in the immediate context of a
659
  template instantiation. — *end note*]
 
663
  `sentinel_for<S, I>`. — *end note*]
664
 
665
  ### `ranges::cbegin` <a id="range.access.cbegin">[[range.access.cbegin]]</a>
666
 
667
  The name `ranges::cbegin` denotes a customization point object
668
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
669
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
670
 
671
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
672
+ `false`, `ranges::cbegin(E)` is ill-formed.
673
+ - Otherwise, let `U` be `ranges::begin(possibly-const-range(t))`.
674
+ `ranges::cbegin(E)` is expression-equivalent to
675
+ `const_iterator<decltype(U)>(U)`.
676
 
677
  [*Note 1*: Whenever `ranges::cbegin(E)` is a valid expression, its type
678
+ models `input_or_output_iterator` and
679
+ `constant-iterator`. — *end note*]
680
 
681
  ### `ranges::cend` <a id="range.access.cend">[[range.access.cend]]</a>
682
 
683
  The name `ranges::cend` denotes a customization point object
684
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
685
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
686
 
687
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
688
+ `false`, `ranges::cend(E)` is ill-formed.
689
+ - Otherwise, let `U` be `ranges::end(possibly-const-range(t))`.
690
+ `ranges::cend(E)` is expression-equivalent to
691
+ `const_sentinel<decltype(U)>(U)`.
692
 
693
  [*Note 1*: Whenever `ranges::cend(E)` is a valid expression, the types
694
+ `S` and `I` of the expressions `ranges::cend(E)` and `ranges::cbegin(E)`
695
+ model `sentinel_for<S, I>`. If `S` models `input_iterator`, then `S`
696
+ also models *`constant-iterator`*. — *end note*]
697
 
698
  ### `ranges::rbegin` <a id="range.access.rbegin">[[range.access.rbegin]]</a>
699
 
700
  The name `ranges::rbegin` denotes a customization point object
701
  [[customization.point.object]].
 
703
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
704
  denotes the reified object for `E`. Then:
705
 
706
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
707
  `false`, `ranges::rbegin(E)` is ill-formed.
708
+ - Otherwise, if `T` is an array type [[term.array.type]] and
709
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rbegin(E)`
710
  is ill-formed with no diagnostic required.
711
+ - Otherwise, if `auto(t.rbegin())` is a valid expression whose type
712
+ models `input_or_output_iterator`, `ranges::rbegin(E)` is
713
+ expression-equivalent to `auto(t.rbegin())`.
714
+ - Otherwise, if `T` is a class or enumeration type and `auto(rbegin(t))`
715
+ is a valid expression whose type models `input_or_output_iterator`
716
+ where the meaning of `rbegin` is established as-if by performing
717
+ argument-dependent lookup only [[basic.lookup.argdep]], then
718
+ `ranges::rbegin(E)` is expression-equivalent to that expression.
 
 
 
 
 
 
 
 
719
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
720
  expressions of the same type which models `bidirectional_iterator`
721
  [[iterator.concept.bidir]], `ranges::rbegin(E)` is
722
  expression-equivalent to `make_reverse_iterator(ranges::end(t))`.
723
  - Otherwise, `ranges::rbegin(E)` is ill-formed.
 
737
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
738
  denotes the reified object for `E`. Then:
739
 
740
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
741
  `false`, `ranges::rend(E)` is ill-formed.
742
+ - Otherwise, if `T` is an array type [[term.array.type]] and
743
  `remove_all_extents_t<T>` is an incomplete type, `ranges::rend(E)` is
744
  ill-formed with no diagnostic required.
745
+ - Otherwise, if `auto(t.rend())` is a valid expression whose type models
746
+ `sentinel_for<decltype({}ranges::rbegin(E))>` then `ranges::rend(E)`
747
+ is expression-equivalent to `auto(t.rend())`.
748
+ - Otherwise, if `T` is a class or enumeration type and `auto(rend(t))`
749
+ is a valid expression whose type models
750
+ `sentinel_for<decltype(ranges::rbegin(E))>` where the meaning of
751
+ `rend` is established as-if by performing argument-dependent lookup
752
+ only [[basic.lookup.argdep]], then `ranges::rend(E)` is
753
+ expression-equivalent to that expression.
 
 
 
 
 
 
 
 
754
  - Otherwise, if both `ranges::begin(t)` and `ranges::end(t)` are valid
755
  expressions of the same type which models `bidirectional_iterator`
756
  [[iterator.concept.bidir]], then `ranges::rend(E)` is
757
  expression-equivalent to `make_reverse_iterator(ranges::begin(t))`.
758
  - Otherwise, `ranges::rend(E)` is ill-formed.
 
760
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
761
  failure when `ranges::rend(E)` appears in the immediate context of a
762
  template instantiation. — *end note*]
763
 
764
  [*Note 2*: Whenever `ranges::rend(E)` is a valid expression, the types
765
+ `S` and `I` of the expressions `ranges::rend(E)` and `ranges::rbegin(E)`
766
+ model `sentinel_for<S, I>`. — *end note*]
767
 
768
  ### `ranges::crbegin` <a id="range.access.crbegin">[[range.access.crbegin]]</a>
769
 
770
  The name `ranges::crbegin` denotes a customization point object
771
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
772
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
773
 
774
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
775
+ `false`, `ranges::crbegin(E)` is ill-formed.
776
+ - Otherwise, let `U` be `ranges::rbegin(possibly-const-range(t))`.
777
+ `ranges::crbegin(E)` is expression-equivalent to
778
+ `const_iterator<decltype(U)>(U)`.
779
 
780
  [*Note 1*: Whenever `ranges::crbegin(E)` is a valid expression, its
781
+ type models `input_or_output_iterator` and
782
+ `constant-iterator`. — *end note*]
783
 
784
  ### `ranges::crend` <a id="range.access.crend">[[range.access.crend]]</a>
785
 
786
  The name `ranges::crend` denotes a customization point object
787
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
788
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
789
 
790
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
791
+ `false`, `ranges::crend(E)` is ill-formed.
792
+ - Otherwise, let `U` be `ranges::rend(possibly-const-range(t))`.
793
+ `ranges::crend(E)` is expression-equivalent to
794
+ `const_sentinel<decltype(U)>(U)`.
795
 
796
  [*Note 1*: Whenever `ranges::crend(E)` is a valid expression, the types
797
+ `S` and `I` of the expressions `ranges::crend(E)` and
798
+ `ranges::crbegin(E)` model `sentinel_for<S, I>`. If `S` models
799
+ `input_iterator`, then `S` also models
800
+ *`constant-iterator`*. — *end note*]
801
 
802
  ### `ranges::size` <a id="range.prim.size">[[range.prim.size]]</a>
803
 
804
  The name `ranges::size` denotes a customization point object
805
  [[customization.point.object]].
806
 
807
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
808
  denotes the reified object for `E`. Then:
809
 
810
+ - If `T` is an array of unknown bound [[term.array.type]],
811
+ `ranges::size(E)` is ill-formed.
812
  - Otherwise, if `T` is an array type, `ranges::size(E)` is
813
+ expression-equivalent to `auto(extent_v<T>)`.
814
  - Otherwise, if `disable_sized_range<remove_cv_t<T>>` [[range.sized]] is
815
+ `false` and `auto(t.size())` is a valid expression of integer-like
816
+ type [[iterator.concept.winc]], `ranges::size(E)` is
817
+ expression-equivalent to `auto({}t.size())`.
818
  - Otherwise, if `T` is a class or enumeration type,
819
+ `disable_sized_range<remove_cv_t<T>>` is `false` and `auto(size(t))`
820
+ is a valid expression of integer-like type where the meaning of `size`
821
+ is established as-if by performing argument-dependent lookup only
822
+ [[basic.lookup.argdep]], then `ranges::size(E)` is
823
+ expression-equivalent to that expression.
 
 
 
 
 
 
 
824
  - Otherwise, if `to-unsigned-like(ranges::end(t) - ranges::begin(t))`
825
  [[ranges.syn]] is a valid expression and the types `I` and `S` of
826
  `ranges::begin(t)` and `ranges::end(t)` (respectively) model both
827
  `sized_sentinel_for<S, I>` [[iterator.concept.sizedsentinel]] and
828
  `forward_iterator<I>`, then `ranges::size(E)` is expression-equivalent
 
837
  is integer-like. — *end note*]
838
 
839
  ### `ranges::ssize` <a id="range.prim.ssize">[[range.prim.ssize]]</a>
840
 
841
  The name `ranges::ssize` denotes a customization point object
842
+ [[customization.point.object]].
 
843
 
844
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
845
+ denotes the reified object for `E`. If `ranges::size(t)` is ill-formed,
846
+ `ranges::ssize(E)` is ill-formed. Otherwise let `D` be
847
+ `make-signed-like-t<decltype(ranges::{}size(t))>`, or `ptrdiff_t` if it
848
+ is wider than that type; `ranges::ssize(E)` is expression-equivalent to
849
+ `static_cast<D>(ranges::size(t))`.
850
 
851
  ### `ranges::empty` <a id="range.prim.empty">[[range.prim.empty]]</a>
852
 
853
  The name `ranges::empty` denotes a customization point object
854
  [[customization.point.object]].
855
 
856
+ Given a subexpression `E` with type `T`, let `t` be an lvalue that
857
+ denotes the reified object for `E`. Then:
858
 
859
+ - If `T` is an array of unknown bound [[term.array.type]],
860
  `ranges::empty(E)` is ill-formed.
861
  - Otherwise, if `bool(t.empty())` is a valid expression,
862
  `ranges::empty(E)` is expression-equivalent to `bool(t.empty())`.
863
  - Otherwise, if `(ranges::size(t) == 0)` is a valid expression,
864
  `ranges::empty(E)` is expression-equivalent to
 
884
  Given a subexpression `E` with type `T`, let `t` be an lvalue that
885
  denotes the reified object for `E`. Then:
886
 
887
  - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
888
  `false`, `ranges::data(E)` is ill-formed.
889
+ - Otherwise, if `T` is an array type [[term.array.type]] and
890
  `remove_all_extents_t<T>` is an incomplete type, `ranges::data(E)` is
891
  ill-formed with no diagnostic required.
892
+ - Otherwise, if `auto(t.data())` is a valid expression of pointer to
893
+ object type, `ranges::data(E)` is expression-equivalent to
894
+ `auto(t.data())`.
895
  - Otherwise, if `ranges::begin(t)` is a valid expression whose type
896
  models `contiguous_iterator`, `ranges::data(E)` is
897
+ expression-equivalent to `to_address(ranges::begin(t))`.
898
  - Otherwise, `ranges::data(E)` is ill-formed.
899
 
900
  [*Note 1*: Diagnosable ill-formed cases above result in substitution
901
  failure when `ranges::data(E)` appears in the immediate context of a
902
  template instantiation. — *end note*]
 
904
  [*Note 2*: Whenever `ranges::data(E)` is a valid expression, it has
905
  pointer to object type. — *end note*]
906
 
907
  ### `ranges::cdata` <a id="range.prim.cdata">[[range.prim.cdata]]</a>
908
 
909
+ ``` cpp
910
+ template<class T>
911
+ constexpr auto as-const-pointer(const T* p) { return p; } // exposition only
912
+ ```
913
+
914
  The name `ranges::cdata` denotes a customization point object
915
+ [[customization.point.object]]. Given a subexpression `E` with type `T`,
916
+ let `t` be an lvalue that denotes the reified object for `E`. Then:
917
 
918
+ - If `E` is an rvalue and `enable_borrowed_range<remove_cv_t<T>>` is
919
+ `false`, `ranges::cdata(E)` is ill-formed.
920
+ - Otherwise, `ranges::cdata(E)` is expression-equivalent to
921
+ `as-const-pointer(ranges::data(possibly-const-range(t)))`.
922
 
923
  [*Note 1*: Whenever `ranges::cdata(E)` is a valid expression, it has
924
+ pointer to constant object type. — *end note*]
925
 
926
  ## Range requirements <a id="range.req">[[range.req]]</a>
927
 
928
  ### General <a id="range.req.general">[[range.req.general]]</a>
929
 
930
+ Ranges are an abstraction that allows a C++ program to operate on
931
  elements of data structures uniformly. Calling `ranges::begin` on a
932
  range returns an object whose type models `input_or_output_iterator`
933
  [[iterator.concept.iterator]]. Calling `ranges::end` on a range returns
934
  an object whose type `S`, together with the type `I` of the object
935
  returned by `ranges::begin`, models `sentinel_for<S, I>`. The library
 
939
 
940
  The `range` concept requires that `ranges::begin` and `ranges::end`
941
  return an iterator and a sentinel, respectively. The `sized_range`
942
  concept refines `range` with the requirement that `ranges::size` be
943
  amortized 𝑂(1). The `view` concept specifies requirements on a `range`
944
+ type to provide operations with predictable complexity.
945
 
946
  Several refinements of `range` group requirements that arise frequently
947
  in concepts and algorithms. Common ranges are ranges for which
948
  `ranges::begin` and `ranges::end` return objects of the same type.
949
  Random access ranges are ranges for which `ranges::begin` returns a type
 
979
  time and non-modifying, and
980
  - if the type of `ranges::begin(t)` models `forward_iterator`,
981
  `ranges::begin(t)` is equality-preserving.
982
 
983
  [*Note 1*: Equality preservation of both `ranges::begin` and
984
+ `ranges::end` enables passing a range whose iterator type models
985
  `forward_iterator` to multiple algorithms and making multiple passes
986
  over the range by repeated calls to `ranges::begin` and `ranges::end`.
987
  Since `ranges::begin` is not required to be equality-preserving when the
988
+ return type does not model `forward_iterator`, it is possible for
989
+ repeated calls to not return equal values or to not be
990
+ well-defined. — *end note*]
991
 
992
  ``` cpp
993
  template<class T>
994
  concept borrowed_range =
995
+ range<T> && (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
 
996
  ```
997
 
998
+ Let `U` be `remove_reference_t<T>` if `T` is an rvalue reference type,
999
+ and `T` otherwise. Given a variable `u` of type `U`, `T` models
1000
+ `borrowed_range` only if the validity of iterators obtained from `u` is
1001
+ not tied to the lifetime of that variable.
1002
 
1003
  [*Note 2*: Since the validity of iterators is not tied to the lifetime
1004
+ of a variable whose type models `borrowed_range`, a function with a
1005
+ parameter of such a type can return iterators obtained from it without
1006
+ danger of dangling. — *end note*]
1007
 
1008
  ``` cpp
1009
  template<class>
1010
+ constexpr bool enable_borrowed_range = false;
1011
  ```
1012
 
1013
  *Remarks:* Pursuant to [[namespace.std]], users may specialize
1014
  `enable_borrowed_range` for cv-unqualified program-defined types. Such
1015
  specializations shall be usable in constant expressions [[expr.const]]
 
1034
  time using `ranges::size`.
1035
 
1036
  ``` cpp
1037
  template<class T>
1038
  concept sized_range =
1039
+ range<T> && requires(T& t) { ranges::size(t); };
 
1040
  ```
1041
 
1042
  Given an lvalue `t` of type `remove_reference_t<T>`, `T` models
1043
  `sized_range` only if
1044
 
1045
  - `ranges::size(t)` is amortized 𝑂(1), does not modify `t`, and is equal
1046
+ to `ranges::distance(ranges::begin(t), ranges::end(t))`, and
1047
  - if `iterator_t<T>` models `forward_iterator`, `ranges::size(t)` is
1048
  well-defined regardless of the evaluation of `ranges::begin(t)`.
1049
  \[*Note 1*: `ranges::size(t)` is otherwise not required to be
1050
+ well-defined after evaluating `ranges::begin(t)`. For example, it is
1051
+ possible for `ranges::size(t)` to be well-defined for a `sized_range`
1052
+ whose iterator type does not model `forward_iterator` only if
1053
+ evaluated before the first call to `ranges::begin(t)`. — *end note*]
1054
 
1055
  ``` cpp
1056
  template<class>
1057
+ constexpr bool disable_sized_range = false;
1058
  ```
1059
 
1060
  *Remarks:* Pursuant to [[namespace.std]], users may specialize
1061
  `disable_sized_range` for cv-unqualified program-defined types. Such
1062
  specializations shall be usable in constant expressions [[expr.const]]
 
1067
  `sized_range`. — *end note*]
1068
 
1069
  ### Views <a id="range.view">[[range.view]]</a>
1070
 
1071
  The `view` concept specifies the requirements of a `range` type that has
1072
+ the semantic properties below, which make it suitable for use in
1073
+ constructing range adaptor pipelines [[range.adaptors]].
 
1074
 
1075
  ``` cpp
1076
  template<class T>
1077
  concept view =
1078
+ range<T> && movable<T> && enable_view<T>;
1079
  ```
1080
 
1081
  `T` models `view` only if:
1082
 
1083
  - `T` has 𝑂(1) move construction; and
1084
+ - move assignment of an object of type `T` is no more complex than
1085
+ destruction followed by move construction; and
1086
+ - if N copies and/or moves are made from an object of type `T` that
1087
+ contained M elements, then those N objects have 𝑂(N+M) destruction;
1088
+ and
1089
  - `copy_constructible<T>` is `false`, or `T` has 𝑂(1) copy construction;
1090
  and
1091
+ - `copyable<T>` is `false`, or copy assignment of an object of type `T`
1092
+ is no more complex than destruction followed by copy construction.
1093
+
1094
+ [*Note 1*: The constraints on copying and moving imply that a
1095
+ moved-from object of type `T` has 𝑂(1) destruction. — *end note*]
1096
 
1097
  [*Example 1*:
1098
 
1099
+ Examples of views are:
1100
 
1101
  - A `range` type that wraps a pair of iterators.
1102
  - A `range` type that holds its elements by `shared_ptr` and shares
1103
  ownership with all its copies.
1104
  - A `range` type that generates its elements on demand.
1105
 
1106
+ A container such as `vector<string>` does not meet the semantic
1107
+ requirements of `view` since copying the container copies all of the
1108
+ elements, which cannot be done in constant time.
1109
 
1110
  — *end example*]
1111
 
1112
  Since the difference between `range` and `view` is largely semantic, the
1113
  two are differentiated with the help of `enable_view`.
1114
 
1115
  ``` cpp
1116
  template<class T>
1117
+ constexpr bool is-derived-from-view-interface = see belownc; // exposition only
1118
+ template<class T>
1119
+ constexpr bool enable_view =
1120
+ derived_from<T, view_base> || is-derived-from-view-interface<T>;
1121
  ```
1122
 
1123
+ For a type `T`, *`is-derived-from-view-interface`*`<T>` is `true` if and
1124
+ only if `T` has exactly one public base class `view_interface<U>` for
1125
+ some type `U` and `T` has no base classes of type `view_interface<V>`
1126
+ for any other type `V`.
1127
+
1128
  *Remarks:* Pursuant to [[namespace.std]], users may specialize
1129
  `enable_view` to `true` for cv-unqualified program-defined types which
1130
  model `view`, and `false` for types which do not. Such specializations
1131
  shall be usable in constant expressions [[expr.const]] and have type
1132
  `const bool`.
 
1159
  concept random_access_range =
1160
  bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
1161
  ```
1162
 
1163
  `contiguous_range` additionally requires that the `ranges::data`
1164
+ customization point object [[range.prim.data]] is usable with the range.
1165
 
1166
  ``` cpp
1167
  template<class T>
1168
  concept contiguous_range =
1169
  random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
 
1186
  template<class T>
1187
  concept common_range =
1188
  range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
1189
  ```
1190
 
1191
+ ``` cpp
1192
+ template<class R>
1193
+ constexpr bool is-initializer-list = see below; // exposition only
1194
+ ```
1195
+
1196
+ For a type `R`, *`is-initializer-list`*`<R>` is `true` if and only if
1197
+ `remove_cvref_t<R>` is a specialization of `initializer_list`.
1198
+
1199
  The `viewable_range` concept specifies the requirements of a `range`
1200
+ type that can be converted to a view safely.
1201
 
1202
  ``` cpp
1203
  template<class T>
1204
  concept viewable_range =
1205
+ range<T> &&
1206
+ ((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||
1207
+ (!view<remove_cvref_t<T>> &&
1208
+ (is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
1209
+ ```
1210
+
1211
+ The `constant_range` concept specifies the requirements of a `range`
1212
+ type whose elements are not modifiable.
1213
+
1214
+ ``` cpp
1215
+ template<class T>
1216
+ concept constant_range =
1217
+ input_range<T> && constant-iterator<iterator_t<T>>;
1218
  ```
1219
 
1220
  ## Range utilities <a id="range.utility">[[range.utility]]</a>
1221
 
1222
+ ### General <a id="range.utility.general">[[range.utility.general]]</a>
1223
+
1224
+ The components in [[range.utility]] are general utilities for
1225
+ representing and manipulating ranges.
1226
 
1227
  ### Helper concepts <a id="range.utility.helpers">[[range.utility.helpers]]</a>
1228
 
1229
  Many of the types in subclause  [[range.utility]] are specified in terms
1230
  of the following exposition-only concepts:
 
1239
  template<class I>
1240
  concept has-arrow = // exposition only
1241
  input_iterator<I> && (is_pointer_v<I> || requires(I i) { i.operator->(); });
1242
 
1243
  template<class T, class U>
1244
+ concept different-from = // exposition only
1245
  !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
1246
+
1247
+ template<class R>
1248
+ concept range-with-movable-references = // exposition only
1249
+ input_range<R> && move_constructible<range_reference_t<R>> &&
1250
+ move_constructible<range_rvalue_reference_t<R>>;
1251
  ```
1252
 
1253
  ### View interface <a id="view.interface">[[view.interface]]</a>
1254
 
1255
+ #### General <a id="view.interface.general">[[view.interface.general]]</a>
1256
+
1257
+ The class template `view_interface` is a helper for defining view-like
1258
  types that offer a container-like interface. It is parameterized with
1259
  the type that is derived from it.
1260
 
1261
  ``` cpp
1262
  namespace std::ranges {
1263
  template<class D>
1264
  requires is_class_v<D> && same_as<D, remove_cv_t<D>>
1265
+ class view_interface {
1266
  private:
1267
  constexpr D& derived() noexcept { // exposition only
1268
  return static_cast<D&>(*this);
1269
  }
1270
  constexpr const D& derived() const noexcept { // exposition only
1271
  return static_cast<const D&>(*this);
1272
  }
1273
+
1274
  public:
1275
+ constexpr bool empty() requires sized_range<D> || forward_range<D> {
1276
+ if constexpr (sized_range<D>)
1277
+ return ranges::size(derived()) == 0;
1278
+ else
1279
  return ranges::begin(derived()) == ranges::end(derived());
1280
  }
1281
+ constexpr bool empty() const requires sized_range<const D> || forward_range<const D> {
1282
+ if constexpr (sized_range<const D>)
1283
+ return ranges::size(derived()) == 0;
1284
+ else
1285
  return ranges::begin(derived()) == ranges::end(derived());
1286
  }
1287
 
1288
+ constexpr auto cbegin() requires input_range<D> {
1289
+ return ranges::cbegin(derived());
1290
+ }
1291
+ constexpr auto cbegin() const requires input_range<const D> {
1292
+ return ranges::cbegin(derived());
1293
+ }
1294
+ constexpr auto cend() requires input_range<D> {
1295
+ return ranges::cend(derived());
1296
+ }
1297
+ constexpr auto cend() const requires input_range<const D> {
1298
+ return ranges::cend(derived());
1299
+ }
1300
+
1301
  constexpr explicit operator bool()
1302
  requires requires { ranges::empty(derived()); } {
1303
  return !ranges::empty(derived());
1304
  }
1305
  constexpr explicit operator bool() const
 
1315
  return to_address(ranges::begin(derived()));
1316
  }
1317
 
1318
  constexpr auto size() requires forward_range<D> &&
1319
  sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
1320
+ return to-unsigned-like(ranges::end(derived()) - ranges::begin(derived()));
1321
  }
1322
  constexpr auto size() const requires forward_range<const D> &&
1323
  sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
1324
+ return to-unsigned-like(ranges::end(derived()) - ranges::begin(derived()));
1325
  }
1326
 
1327
  constexpr decltype(auto) front() requires forward_range<D>;
1328
  constexpr decltype(auto) front() const requires forward_range<const D>;
1329
 
 
1354
  ``` cpp
1355
  constexpr decltype(auto) front() requires forward_range<D>;
1356
  constexpr decltype(auto) front() const requires forward_range<const D>;
1357
  ```
1358
 
1359
+ *Preconditions:* `!empty()` is `true`.
1360
 
1361
  *Effects:* Equivalent to: `return *ranges::begin(`*`derived`*`());`
1362
 
1363
  ``` cpp
1364
  constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
1365
  constexpr decltype(auto) back() const
1366
  requires bidirectional_range<const D> && common_range<const D>;
1367
  ```
1368
 
1369
+ *Preconditions:* `!empty()` is `true`.
1370
 
1371
  *Effects:* Equivalent to:
1372
  `return *ranges::prev(ranges::end(`*`derived`*`()));`
1373
 
1374
  ### Sub-ranges <a id="range.subrange">[[range.subrange]]</a>
1375
 
1376
+ #### General <a id="range.subrange.general">[[range.subrange.general]]</a>
1377
+
1378
  The `subrange` class template combines together an iterator and a
1379
  sentinel into a single object that models the `view` concept.
1380
  Additionally, it models the `sized_range` concept when the final
1381
  template parameter is `subrange_kind::sized`.
1382
 
1383
  ``` cpp
1384
  namespace std::ranges {
1385
+ template<class From, class To>
1386
+ concept uses-nonqualification-pointer-conversion = // exposition only
1387
+ is_pointer_v<From> && is_pointer_v<To> &&
1388
+ !convertible_to<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>;
1389
+
1390
  template<class From, class To>
1391
  concept convertible-to-non-slicing = // exposition only
1392
  convertible_to<From, To> &&
1393
+ !uses-nonqualification-pointer-conversion<decay_t<From>, decay_t<To>>;
 
 
 
 
 
 
 
 
 
 
 
 
 
1394
 
1395
  template<class T, class U, class V>
1396
  concept pair-like-convertible-from = // exposition only
1397
+ !range<T> && !is_reference_v<T> && pair-like<T> &&
1398
  constructible_from<T, U, V> &&
1399
  convertible-to-non-slicing<U, tuple_element_t<0, T>> &&
1400
  convertible_to<V, tuple_element_t<1, T>>;
1401
 
 
 
 
 
 
1402
  template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
1403
  sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
1404
  requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
1405
  class subrange : public view_interface<subrange<I, S, K>> {
1406
  private:
1407
  static constexpr bool StoreSize = // exposition only
1408
  K == subrange_kind::sized && !sized_sentinel_for<S, I>;
1409
  I begin_ = I(); // exposition only
1410
  S end_ = S(); // exposition only
1411
  make-unsigned-like-t<iter_difference_t<I>> size_ = 0; // exposition only; present only
1412
+ // if StoreSize is true
1413
  public:
1414
+ subrange() requires default_initializable<I> = default;
1415
 
1416
  constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
1417
 
1418
  constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
1419
  make-unsigned-like-t<iter_difference_t<I>> n)
1420
  requires (K == subrange_kind::sized);
1421
 
1422
+ template<different-from<subrange> R>
1423
  requires borrowed_range<R> &&
1424
  convertible-to-non-slicing<iterator_t<R>, I> &&
1425
  convertible_to<sentinel_t<R>, S>
1426
  constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
1427
 
1428
  template<borrowed_range R>
1429
  requires convertible-to-non-slicing<iterator_t<R>, I> &&
1430
  convertible_to<sentinel_t<R>, S>
1431
  constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
1432
  requires (K == subrange_kind::sized)
1433
+ : subrange{ranges::begin(r), ranges::end(r), n} {}
 
1434
 
1435
+ template<different-from<subrange> PairLike>
1436
  requires pair-like-convertible-from<PairLike, const I&, const S&>
1437
  constexpr operator PairLike() const;
1438
 
1439
  constexpr I begin() const requires copyable<I>;
1440
  [[nodiscard]] constexpr I begin() requires (!copyable<I>);
 
1457
 
1458
  template<input_or_output_iterator I, sentinel_for<I> S>
1459
  subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) ->
1460
  subrange<I, S, subrange_kind::sized>;
1461
 
 
 
 
 
 
 
 
1462
  template<borrowed_range R>
1463
  subrange(R&&) ->
1464
  subrange<iterator_t<R>, sentinel_t<R>,
1465
  (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
1466
  ? subrange_kind::sized : subrange_kind::unsized>;
1467
 
1468
  template<borrowed_range R>
1469
  subrange(R&&, make-unsigned-like-t<range_difference_t<R>>) ->
1470
  subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
 
 
 
 
 
 
 
 
 
 
 
 
1471
  }
1472
  ```
1473
 
1474
  #### Constructors and conversions <a id="range.subrange.ctor">[[range.subrange.ctor]]</a>
1475
 
 
1487
  make-unsigned-like-t<iter_difference_t<I>> n)
1488
  requires (K == subrange_kind::sized);
1489
  ```
1490
 
1491
  *Preconditions:* \[`i`, `s`) is a valid range, and
1492
+ `n == `*`to-unsigned-like`*`(ranges::distance(i, s))` is `true`.
1493
 
1494
  *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
1495
  `s`. If *StoreSize* is `true`, initializes *size\_* with `n`.
1496
 
1497
  [*Note 1*: Accepting the length of the range and storing it to later
1498
  return from `size()` enables `subrange` to model `sized_range` even when
1499
  it stores an iterator and sentinel that do not model
1500
  `sized_sentinel_for`. — *end note*]
1501
 
1502
  ``` cpp
1503
+ template<different-from<subrange> R>
1504
  requires borrowed_range<R> &&
1505
  convertible-to-non-slicing<iterator_t<R>, I> &&
1506
  convertible_to<sentinel_t<R>, S>
1507
  constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
1508
  ```
1509
 
1510
  *Effects:* Equivalent to:
1511
 
1512
+ - If *StoreSize* is `true`,
1513
+ `subrange(r, static_cast<decltype(`*`size_`*`)>(ranges::size(r)))`.
1514
+ - Otherwise, `subrange(ranges::begin(r), ranges::end(r))`.
1515
 
1516
  ``` cpp
1517
+ template<different-from<subrange> PairLike>
1518
  requires pair-like-convertible-from<PairLike, const I&, const S&>
1519
  constexpr operator PairLike() const;
1520
  ```
1521
 
1522
  *Effects:* Equivalent to: `return PairLike(`*`begin_`*`, `*`end_`*`);`
 
1599
  constexpr subrange& advance(iter_difference_t<I> n);
1600
  ```
1601
 
1602
  *Effects:* Equivalent to:
1603
 
 
1604
  ``` cpp
1605
+ if constexpr (bidirectional_iterator<I>) {
1606
+ if (n < 0) {
1607
+ ranges::advance(begin_, n);
1608
+ if constexpr (StoreSize)
1609
+ size_ += to-unsigned-like(-n);
1610
+ return *this;
1611
+ }
1612
+ }
1613
+
1614
  auto d = n - ranges::advance(begin_, n, end_);
1615
+ if constexpr (StoreSize)
1616
  size_ -= to-unsigned-like(d);
 
 
 
 
 
 
 
1617
  return *this;
1618
  ```
1619
 
1620
  ``` cpp
1621
  template<size_t N, class I, class S, subrange_kind K>
1622
+ requires ((N == 0 && copyable<I>) || N == 1)
1623
  constexpr auto get(const subrange<I, S, K>& r);
1624
  template<size_t N, class I, class S, subrange_kind K>
1625
  requires (N < 2)
1626
  constexpr auto get(subrange<I, S, K>&& r);
1627
  ```
 
1635
  return r.end();
1636
  ```
1637
 
1638
  ### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
1639
 
1640
+ The type `dangling` is used together with the template aliases
1641
+ `borrowed_iterator_t` and `borrowed_subrange_t`. When an algorithm that
1642
+ typically returns an iterator into, or a subrange of, a range argument
1643
+ is called with an rvalue range argument that does not model
1644
+ `borrowed_range` [[range.range]], the return value possibly refers to a
1645
+ range whose lifetime has ended. In such cases, the type `dangling` is
1646
+ returned instead of an iterator or subrange.
1647
 
1648
  ``` cpp
1649
  namespace std::ranges {
1650
  struct dangling {
1651
  constexpr dangling() noexcept = default;
1652
+ constexpr dangling(auto&&...) noexcept {}
 
1653
  };
1654
  }
1655
  ```
1656
 
1657
  [*Example 1*:
 
1661
  auto result1 = ranges::find(f(), 42); // #1
1662
  static_assert(same_as<decltype(result1), ranges::dangling>);
1663
  auto vec = f();
1664
  auto result2 = ranges::find(vec, 42); // #2
1665
  static_assert(same_as<decltype(result2), vector<int>::iterator>);
1666
+ auto result3 = ranges::find(ranges::subrange{vec}, 42); // #3
1667
  static_assert(same_as<decltype(result3), vector<int>::iterator>);
1668
  ```
1669
 
1670
  The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
1671
+ is an rvalue `vector`; it is possible for the `vector` to be destroyed
1672
  before a returned iterator is dereferenced. However, the calls at \#2
1673
  and \#3 both return iterators since the lvalue `vec` and specializations
1674
  of `subrange` model `borrowed_range`.
1675
 
1676
  — *end example*]
1677
 
1678
+ For a type `R` that models `range`:
1679
+
1680
+ - if `R` models `borrowed_range`, then `borrowed_iterator_t<R>` denotes
1681
+ `iterator_t<R>`, and `borrowed_subrange_t<R>` denotes
1682
+ `subrange<iterator_t<R>>`;
1683
+ - otherwise, both `borrowed_iterator_t<R>` and `borrowed_subrange_t<R>`
1684
+ denote `dangling`.
1685
+
1686
+ ### Class template `elements_of` <a id="range.elementsof">[[range.elementsof]]</a>
1687
+
1688
+ Specializations of `elements_of` encapsulate a range and act as a tag in
1689
+ overload sets to disambiguate when a range should be treated as a
1690
+ sequence rather than a single value.
1691
+
1692
+ [*Example 1*:
1693
+
1694
+ ``` cpp
1695
+ template<bool YieldElements>
1696
+ generator<any> f(ranges::input_range auto&& r) {
1697
+ if constexpr (YieldElements)
1698
+ co_yield ranges::elements_of(r); // yield each element of r
1699
+ else
1700
+ co_yield r; // yield r as a single value
1701
+ }
1702
+ ```
1703
+
1704
+ — *end example*]
1705
+
1706
+ ``` cpp
1707
+ namespace std::ranges {
1708
+ template<range R, class Allocator = allocator<byte>>
1709
+ struct elements_of {
1710
+ [[no_unique_address]] R range;
1711
+ [[no_unique_address]] Allocator allocator = Allocator();
1712
+ };
1713
+
1714
+ template<class R, class Allocator = allocator<byte>>
1715
+ elements_of(R&&, Allocator = Allocator()) -> elements_of<R&&, Allocator>;
1716
+ }
1717
+ ```
1718
+
1719
+ ### Range conversions <a id="range.utility.conv">[[range.utility.conv]]</a>
1720
+
1721
+ #### General <a id="range.utility.conv.general">[[range.utility.conv.general]]</a>
1722
+
1723
+ The range conversion functions construct an object (usually a container)
1724
+ from a range, by using a constructor taking a range, a `from_range_t`
1725
+ tagged constructor, or a constructor taking a pair of iterators, or by
1726
+ inserting each element of the range into the default-constructed object.
1727
+
1728
+ `ranges::to` is applied recursively, allowing the conversion of a range
1729
+ of ranges.
1730
+
1731
+ [*Example 1*:
1732
+
1733
+ ``` cpp
1734
+ string_view str = "the quick brown fox";
1735
+ auto words = views::split(str, ' ') | to<vector<string>>();
1736
+ // words is vector<string>{"the", "quick", "brown", "fox"}
1737
+ ```
1738
+
1739
+ — *end example*]
1740
+
1741
+ Let *`reservable-container`* be defined as follows:
1742
+
1743
+ ``` cpp
1744
+ template<class Container>
1745
+ constexpr bool reservable-container = // exposition only
1746
+ sized_range<Container> &&
1747
+ requires(Container& c, range_size_t<Container> n) {
1748
+ c.reserve(n);
1749
+ { c.capacity() } -> same_as<decltype(n)>;
1750
+ { c.max_size() } -> same_as<decltype(n)>;
1751
+ };
1752
+ ```
1753
+
1754
+ Let *`container-insertable`* be defined as follows:
1755
+
1756
+ ``` cpp
1757
+ template<class Container, class Ref>
1758
+ constexpr bool container-insertable = // exposition only
1759
+ requires(Container& c, Ref&& ref) {
1760
+ requires (requires { c.push_back(std::forward<Ref>(ref)); } ||
1761
+ requires { c.insert(c.end(), std::forward<Ref>(ref)); });
1762
+ };
1763
+ ```
1764
+
1765
+ Let *`container-inserter`* be defined as follows:
1766
+
1767
+ ``` cpp
1768
+ template<class Ref, class Container>
1769
+ constexpr auto container-inserter(Container& c) { // exposition only
1770
+ if constexpr (requires { c.push_back(declval<Ref>()); })
1771
+ return back_inserter(c);
1772
+ else
1773
+ return inserter(c, c.end());
1774
+ }
1775
+ ```
1776
+
1777
+ #### `ranges::to` <a id="range.utility.conv.to">[[range.utility.conv.to]]</a>
1778
+
1779
+ ``` cpp
1780
+ template<class C, input_range R, class... Args> requires (!view<C>)
1781
+ constexpr C to(R&& r, Args&&... args);
1782
+ ```
1783
+
1784
+ *Mandates:* `C` is a cv-unqualified class type.
1785
+
1786
+ *Returns:* An object of type `C` constructed from the elements of `r` in
1787
+ the following manner:
1788
+
1789
+ - If `C` does not satisfy `input_range` or
1790
+ `convertible_to<range_reference_t<R>, range_value_t<C>>` is `true`:
1791
+ - If `constructible_from<C, R, Args...>` is `true`:
1792
+ ``` cpp
1793
+ C(std::forward<R>(r), std::forward<Args>(args)...)
1794
+ ```
1795
+ - Otherwise, if `constructible_from<C, from_range_t, R, Args...>` is
1796
+ `true`:
1797
+ ``` cpp
1798
+ C(from_range, std::forward<R>(r), std::forward<Args>(args)...)
1799
+ ```
1800
+ - Otherwise, if
1801
+ - `common_range<R>` is `true`,
1802
+ - the *qualified-id*
1803
+ `iterator_traits<iterator_t<R>>::iterator_category` is valid and
1804
+ denotes a type that models `derived_from<input_iterator_tag>`, and
1805
+ - `constructible_from<C, iterator_t<R>, sentinel_t<R>, Args...>` is
1806
+ `true`:
1807
+
1808
+ ``` cpp
1809
+ C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)
1810
+ ```
1811
+ - Otherwise, if
1812
+ - `constructible_from<C, Args...>` is `true`, and
1813
+ - *`container-insertable`*`<C, range_reference_t<R>>` is `true`:
1814
+
1815
+ ``` cpp
1816
+ C c(std::forward<Args>(args)...);
1817
+ if constexpr (sized_range<R> && reservable-container<C>)
1818
+ c.reserve(static_cast<range_size_t<C>>(ranges::size(r)));
1819
+ ranges::copy(r, container-inserter<range_reference_t<R>>(c));
1820
+ ```
1821
+ - Otherwise, if `input_range<range_reference_t<R>>` is `true`:
1822
+ ``` cpp
1823
+ to<C>(r | views::transform([](auto&& elem) {
1824
+ return to<range_value_t<C>>(std::forward<decltype(elem)>(elem));
1825
+ }), std::forward<Args>(args)...);
1826
+ ```
1827
+ - Otherwise, the program is ill-formed.
1828
+
1829
+ ``` cpp
1830
+ template<template<class...> class C, input_range R, class... Args>
1831
+ constexpr auto to(R&& r, Args&&... args);
1832
+ ```
1833
+
1834
+ Let *input-iterator* be an exposition-only type:
1835
+
1836
+ ``` cpp
1837
+ struct input-iterator { // exposition only
1838
+ using iterator_category = input_iterator_tag;
1839
+ using value_type = range_value_t<R>;
1840
+ using difference_type = ptrdiff_t;
1841
+ using pointer = add_pointer_t<range_reference_t<R>>;
1842
+ using reference = range_reference_t<R>;
1843
+ reference operator*() const;
1844
+ pointer operator->() const;
1845
+ input-iterator& operator++();
1846
+ input-iterator operator++(int);
1847
+ bool operator==(const input-iterator&) const;
1848
+ };
1849
+ ```
1850
+
1851
+ [*Note 1*: *input-iterator* meets the syntactic requirements of
1852
+ *Cpp17InputIterator*. — *end note*]
1853
+
1854
+ Let *`DEDUCE_EXPR`* be defined as follows:
1855
+
1856
+ - `C(declval<R>(), declval<Args>()...)` if that is a valid expression,
1857
+ - otherwise, `C(from_range, declval<R>(), declval<Args>()...)` if that
1858
+ is a valid expression,
1859
+ - otherwise,
1860
+ ``` cpp
1861
+ C(declval<input-iterator>(), declval<input-iterator>(), declval<Args>()...)
1862
+ ```
1863
+
1864
+ if that is a valid expression,
1865
+ - otherwise, the program is ill-formed.
1866
+
1867
+ *Returns:*
1868
+ `to<decltype(`*`DEDUCE_EXPR`*`)>(std::forward<R>(r), std::forward<Args>(args)...)`.
1869
+
1870
+ #### `ranges::to` adaptors <a id="range.utility.conv.adaptors">[[range.utility.conv.adaptors]]</a>
1871
+
1872
+ ``` cpp
1873
+ template<class C, class... Args> requires (!view<C>)
1874
+ constexpr auto to(Args&&... args);
1875
+ template<template<class...> class C, class... Args>
1876
+ constexpr auto to(Args&&... args);
1877
+ ```
1878
+
1879
+ *Mandates:* For the first overload, `C` is a cv-unqualified class type.
1880
+
1881
+ *Returns:* A range adaptor closure object [[range.adaptor.object]] `f`
1882
+ that is a perfect forwarding call
1883
+ wrapper [[term.perfect.forwarding.call.wrapper]] with the following
1884
+ properties:
1885
+
1886
+ - It has no target object.
1887
+ - Its bound argument entities `bound_args` consist of objects of types
1888
+ `decay_t<Args>...` direct-non-list-initialized with
1889
+ `std::forward<Args>(args)...`, respectively.
1890
+ - Its call pattern is `to<C>(r, bound_args...)`, where `r` is the
1891
+ argument used in a function call expression of `f`.
1892
+
1893
  ## Range factories <a id="range.factories">[[range.factories]]</a>
1894
 
1895
+ ### General <a id="range.factories.general">[[range.factories.general]]</a>
1896
+
1897
+ Subclause [[range.factories]] defines *range factories*, which are
1898
+ utilities to create a view.
1899
 
1900
  Range factories are declared in namespace `std::ranges::views`.
1901
 
1902
  ### Empty view <a id="range.empty">[[range.empty]]</a>
1903
 
1904
  #### Overview <a id="range.empty.overview">[[range.empty.overview]]</a>
1905
 
1906
+ `empty_view` produces a view of no elements of a particular type.
1907
 
1908
  [*Example 1*:
1909
 
1910
  ``` cpp
1911
+ auto e = views::empty<int>;
1912
  static_assert(ranges::empty(e));
1913
  static_assert(0 == e.size());
1914
  ```
1915
 
1916
  — *end example*]
 
1934
 
1935
  ### Single view <a id="range.single">[[range.single]]</a>
1936
 
1937
  #### Overview <a id="range.single.overview">[[range.single.overview]]</a>
1938
 
1939
+ `single_view` produces a view that contains exactly one element of a
1940
  specified value.
1941
 
1942
  The name `views::single` denotes a customization point object
1943
  [[customization.point.object]]. Given a subexpression `E`, the
1944
  expression `views::single(E)` is expression-equivalent to
1945
+ `single_view<decay_t<decltype((E))>>(E)`.
1946
 
1947
  [*Example 1*:
1948
 
1949
  ``` cpp
1950
+ for (int i : views::single(4))
 
1951
  cout << i; // prints 4
1952
  ```
1953
 
1954
  — *end example*]
1955
 
1956
  #### Class template `single_view` <a id="range.single.view">[[range.single.view]]</a>
1957
 
1958
  ``` cpp
1959
  namespace std::ranges {
1960
+ template<move_constructible T>
1961
  requires is_object_v<T>
1962
  class single_view : public view_interface<single_view<T>> {
1963
  private:
1964
+ movable-box<T> value_; // exposition only{} (see [range.move.wrap])
1965
+
1966
  public:
1967
+ single_view() requires default_initializable<T> = default;
1968
+ constexpr explicit single_view(const T& t) requires copy_constructible<T>;
1969
  constexpr explicit single_view(T&& t);
1970
  template<class... Args>
1971
  requires constructible_from<T, Args...>
1972
+ constexpr explicit single_view(in_place_t, Args&&... args);
1973
 
1974
  constexpr T* begin() noexcept;
1975
  constexpr const T* begin() const noexcept;
1976
  constexpr T* end() noexcept;
1977
  constexpr const T* end() const noexcept;
1978
  static constexpr size_t size() noexcept;
1979
  constexpr T* data() noexcept;
1980
  constexpr const T* data() const noexcept;
1981
  };
1982
+
1983
+ template<class T>
1984
+ single_view(T) -> single_view<T>;
1985
  }
1986
  ```
1987
 
1988
  ``` cpp
1989
+ constexpr explicit single_view(const T& t) requires copy_constructible<T>;
1990
  ```
1991
 
1992
  *Effects:* Initializes *value\_* with `t`.
1993
 
1994
  ``` cpp
 
1997
 
1998
  *Effects:* Initializes *value\_* with `std::move(t)`.
1999
 
2000
  ``` cpp
2001
  template<class... Args>
2002
+ requires constructible_from<T, Args...>
2003
+ constexpr explicit single_view(in_place_t, Args&&... args);
2004
  ```
2005
 
2006
  *Effects:* Initializes *value\_* as if by
2007
  *`value_`*`{in_place, std::forward<Args>(args)...}`.
2008
 
 
2041
  an initial value.
2042
 
2043
  The name `views::iota` denotes a customization point object
2044
  [[customization.point.object]]. Given subexpressions `E` and `F`, the
2045
  expressions `views::iota(E)` and `views::iota(E, F)` are
2046
+ expression-equivalent to `iota_view(E)` and `iota_view(E, F)`,
2047
  respectively.
2048
 
2049
  [*Example 1*:
2050
 
2051
  ``` cpp
2052
+ for (int i : views::iota(1, 10))
2053
+ cout << i << ' '; // prints 1 2 3 4 5 6 7 8 9
2054
  ```
2055
 
2056
  — *end example*]
2057
 
2058
  #### Class template `iota_view` <a id="range.iota.view">[[range.iota.view]]</a>
2059
 
2060
  ``` cpp
2061
  namespace std::ranges {
2062
  template<class I>
2063
+ concept exposition onlyconceptnc{decrementable} = see belownc; // exposition only
2064
+
2065
  template<class I>
2066
+ concept exposition onlyconceptnc{advanceable} = see belownc; // exposition only
 
2067
 
2068
  template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
2069
+ requires weakly-equality-comparable-with<W, Bound> && copyable<W>
2070
  class iota_view : public view_interface<iota_view<W, Bound>> {
2071
  private:
2072
  // [range.iota.iterator], class iota_view::iterator
2073
  struct iterator; // exposition only
2074
+
2075
  // [range.iota.sentinel], class iota_view::sentinel
2076
  struct sentinel; // exposition only
2077
+
2078
  W value_ = W(); // exposition only
2079
  Bound bound_ = Bound(); // exposition only
2080
+
2081
  public:
2082
+ iota_view() requires default_initializable<W> = default;
2083
  constexpr explicit iota_view(W value);
2084
+ constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
2085
+ constexpr explicit iota_view(iterator first, see below last);
 
2086
 
2087
  constexpr iterator begin() const;
2088
  constexpr auto end() const;
2089
  constexpr iterator end() const requires same_as<W, Bound>;
2090
 
 
2112
 
2113
  The exposition-only *decrementable* concept is equivalent to:
2114
 
2115
  ``` cpp
2116
  template<class I>
2117
+ concept decrementable = // exposition only
2118
  incrementable<I> && requires(I i) {
2119
  { --i } -> same_as<I&>;
2120
  { i-- } -> same_as<I>;
2121
  };
2122
  ```
 
2136
 
2137
  The exposition-only *advanceable* concept is equivalent to:
2138
 
2139
  ``` cpp
2140
  template<class I>
2141
+ concept advanceable = // exposition only
2142
  decrementable<I> && totally_ordered<I> &&
2143
  requires(I i, const I j, const IOTA-DIFF-T(I) n) {
2144
  { i += n } -> same_as<I&>;
2145
  { i -= n } -> same_as<I&>;
2146
  I(j + n);
 
2174
  ``` cpp
2175
  constexpr explicit iota_view(W value);
2176
  ```
2177
 
2178
  *Preconditions:* `Bound` denotes `unreachable_sentinel_t` or `Bound()`
2179
+ is reachable from `value`. When `W` and `Bound` model
2180
+ `totally_ordered_with`, then `bool(value <= Bound())` is `true`.
2181
 
2182
  *Effects:* Initializes *value\_* with `value`.
2183
 
2184
  ``` cpp
2185
+ constexpr explicit iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
2186
  ```
2187
 
2188
  *Preconditions:* `Bound` denotes `unreachable_sentinel_t` or `bound` is
2189
  reachable from `value`. When `W` and `Bound` model
2190
  `totally_ordered_with`, then `bool(value <= bound)` is `true`.
2191
 
2192
  *Effects:* Initializes *value\_* with `value` and *bound\_* with
2193
  `bound`.
2194
 
2195
+ ``` cpp
2196
+ constexpr explicit iota_view(iterator first, see below last);
2197
+ ```
2198
+
2199
+ *Effects:* Equivalent to:
2200
+
2201
+ - If `same_as<W, Bound>` is `true`,
2202
+ `iota_view(first.`*`value_`*`, last.`*`value_`*`)`.
2203
+ - Otherwise, if `Bound` denotes `unreachable_sentinel_t`,
2204
+ `iota_view(first.`*`value_`*`, last)`.
2205
+ - Otherwise, `iota_view(first.`*`value_`*`, last.`*`bound_`*`)`.
2206
+
2207
+ *Remarks:* The type of `last` is:
2208
+
2209
+ - If `same_as<W, Bound>` is `true`, *iterator*.
2210
+ - Otherwise, if `Bound` denotes `unreachable_sentinel_t`, `Bound`.
2211
+ - Otherwise, *sentinel*.
2212
+
2213
  ``` cpp
2214
  constexpr iterator begin() const;
2215
  ```
2216
 
2217
+ *Effects:* Equivalent to: `return `*`iterator`*`{`*`value_`*`};`
2218
 
2219
  ``` cpp
2220
  constexpr auto end() const;
2221
  ```
2222
 
 
2231
 
2232
  ``` cpp
2233
  constexpr iterator end() const requires same_as<W, Bound>;
2234
  ```
2235
 
2236
+ *Effects:* Equivalent to: `return `*`iterator`*`{`*`bound_`*`};`
2237
 
2238
  ``` cpp
2239
  constexpr auto size() const requires see below;
2240
  ```
2241
 
 
2250
  : to-unsigned-like(bound_) - to-unsigned-like(value_);
2251
  else
2252
  return to-unsigned-like(bound_ - value_);
2253
  ```
2254
 
2255
+ *Remarks:* The expression in the *requires-clause* is equivalent to:
2256
 
2257
  ``` cpp
2258
+ (same_as<W, Bound> && advanceable<W>) || (is-integer-like<W> && is-integer-like<Bound>) ||
2259
  sized_sentinel_for<Bound, W>
2260
  ```
2261
 
2262
  #### Class `iota_view::iterator` <a id="range.iota.iterator">[[range.iota.iterator]]</a>
2263
 
2264
  ``` cpp
2265
  namespace std::ranges {
2266
  template<weakly_incrementable W, semiregular Bound>
2267
+ requires weakly-equality-comparable-with<W, Bound> && copyable<W>
2268
  struct iota_view<W, Bound>::iterator {
2269
  private:
2270
  W value_ = W(); // exposition only
2271
+
2272
  public:
2273
  using iterator_concept = see below;
2274
+ using iterator_category = input_iterator_tag; // present only if W models incrementable and
2275
+ // IOTA-DIFF-T(W) is an integral type
2276
  using value_type = W;
2277
  using difference_type = IOTA-DIFF-T(W);
2278
 
2279
+ iterator() requires default_initializable<W> = default;
2280
  constexpr explicit iterator(W value);
2281
 
2282
  constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
2283
 
2284
  constexpr iterator& operator++();
 
2492
  ``` cpp
2493
  friend constexpr iterator operator+(iterator i, difference_type n)
2494
  requires advanceable<W>;
2495
  ```
2496
 
2497
+ *Effects:* Equivalent to:
2498
+
2499
+ ``` cpp
2500
+ i += n;
2501
+ return i;
2502
+ ```
2503
 
2504
  ``` cpp
2505
  friend constexpr iterator operator+(difference_type n, iterator i)
2506
  requires advanceable<W>;
2507
  ```
 
2511
  ``` cpp
2512
  friend constexpr iterator operator-(iterator i, difference_type n)
2513
  requires advanceable<W>;
2514
  ```
2515
 
2516
+ *Effects:* Equivalent to:
2517
+
2518
+ ``` cpp
2519
+ i -= n;
2520
+ return i;
2521
+ ```
2522
 
2523
  ``` cpp
2524
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
2525
  requires advanceable<W>;
2526
  ```
 
2544
  #### Class `iota_view::sentinel` <a id="range.iota.sentinel">[[range.iota.sentinel]]</a>
2545
 
2546
  ``` cpp
2547
  namespace std::ranges {
2548
  template<weakly_incrementable W, semiregular Bound>
2549
+ requires weakly-equality-comparable-with<W, Bound> && copyable<W>
2550
  struct iota_view<W, Bound>::sentinel {
2551
  private:
2552
  Bound bound_ = Bound(); // exposition only
2553
+
2554
  public:
2555
  sentinel() = default;
2556
  constexpr explicit sentinel(Bound bound);
2557
 
2558
  friend constexpr bool operator==(const iterator& x, const sentinel& y);
 
2589
  requires sized_sentinel_for<Bound, W>;
2590
  ```
2591
 
2592
  *Effects:* Equivalent to: `return -(y - x);`
2593
 
2594
+ ### Repeat view <a id="range.repeat">[[range.repeat]]</a>
2595
+
2596
+ #### Overview <a id="range.repeat.overview">[[range.repeat.overview]]</a>
2597
+
2598
+ `repeat_view` generates a sequence of elements by repeatedly producing
2599
+ the same value.
2600
+
2601
+ The name `views::repeat` denotes a customization point object
2602
+ [[customization.point.object]]. Given subexpressions `E` and `F`, the
2603
+ expressions `views::repeat(E)` and `views::repeat(E, F)` are
2604
+ expression-equivalent to `repeat_view(E)` and `repeat_view(E, F)`,
2605
+ respectively.
2606
+
2607
+ [*Example 1*:
2608
+
2609
+ ``` cpp
2610
+ for (int i : views::repeat(17, 4))
2611
+ cout << i << ' ';
2612
+ // prints 17 17 17 17
2613
+ ```
2614
+
2615
+ — *end example*]
2616
+
2617
+ #### Class template `repeat_view` <a id="range.repeat.view">[[range.repeat.view]]</a>
2618
+
2619
+ ``` cpp
2620
+ namespace std::ranges {
2621
+ template<class T>
2622
+ concept integer-like-with-usable-difference-type = // exposition only
2623
+ is-signed-integer-like<T> || (is-integer-like<T> && weakly_incrementable<T>);
2624
+
2625
+ template<move_constructible T, semiregular Bound = unreachable_sentinel_t>
2626
+ requires (is_object_v<T> && same_as<T, remove_cv_t<T>> &&
2627
+ (integer-like-with-usable-difference-type<Bound> ||
2628
+ same_as<Bound, unreachable_sentinel_t>))
2629
+ class repeat_view : public view_interface<repeat_view<T, Bound>> {
2630
+ private:
2631
+ // [range.repeat.iterator], class repeat_view::iterator
2632
+ struct iterator; // exposition only
2633
+
2634
+ movable-box<T> value_; // exposition only, see [range.move.wrap]
2635
+ Bound bound_ = Bound(); // exposition only
2636
+
2637
+ public:
2638
+ repeat_view() requires default_initializable<T> = default;
2639
+
2640
+ constexpr explicit repeat_view(const T& value, Bound bound = Bound())
2641
+ requires copy_constructible<T>;
2642
+ constexpr explicit repeat_view(T&& value, Bound bound = Bound());
2643
+ template<class... TArgs, class... BoundArgs>
2644
+ requires constructible_from<T, TArgs...> &&
2645
+ constructible_from<Bound, BoundArgs...>
2646
+ constexpr explicit repeat_view(piecewise_construct_t,
2647
+ tuple<TArgs...> value_args, tuple<BoundArgs...> bound_args = tuple<>{});
2648
+
2649
+ constexpr iterator begin() const;
2650
+ constexpr iterator end() const requires (!same_as<Bound, unreachable_sentinel_t>);
2651
+ constexpr unreachable_sentinel_t end() const noexcept;
2652
+
2653
+ constexpr auto size() const requires (!same_as<Bound, unreachable_sentinel_t>);
2654
+ };
2655
+
2656
+ template<class T, class Bound>
2657
+ repeat_view(T, Bound) -> repeat_view<T, Bound>;
2658
+ }
2659
+ ```
2660
+
2661
+ ``` cpp
2662
+ constexpr explicit repeat_view(const T& value, Bound bound = Bound())
2663
+ requires copy_constructible<T>;
2664
+ ```
2665
+
2666
+ *Preconditions:* If `Bound` is not `unreachable_sentinel_t`,
2667
+ `bound` ≥ 0.
2668
+
2669
+ *Effects:* Initializes *value\_* with `value` and *bound\_* with
2670
+ `bound`.
2671
+
2672
+ ``` cpp
2673
+ constexpr explicit repeat_view(T&& value, Bound bound = Bound());
2674
+ ```
2675
+
2676
+ *Preconditions:* If `Bound` is not `unreachable_sentinel_t`,
2677
+ `bound` ≥ 0.
2678
+
2679
+ *Effects:* Initializes *value\_* with `std::move(value)` and *bound\_*
2680
+ with `bound`.
2681
+
2682
+ ``` cpp
2683
+ template<class... TArgs, class... BoundArgs>
2684
+ requires constructible_from<T, TArgs...> &&
2685
+ constructible_from<Bound, BoundArgs...>
2686
+ constexpr explicit repeat_view(piecewise_construct_t,
2687
+ tuple<TArgs...> value_args, tuple<BoundArgs...> bound_args = tuple<>{});
2688
+ ```
2689
+
2690
+ *Effects:* Initializes *value\_* with
2691
+ `make_from_tuple<T>(std::move(value_args))` and initializes *bound\_*
2692
+ with `make_from_tuple<Bound>(std::move(bound_args))`. The behavior is
2693
+ undefined if `Bound` is not `unreachable_sentinel_t` and *bound\_* is
2694
+ negative.
2695
+
2696
+ ``` cpp
2697
+ constexpr iterator begin() const;
2698
+ ```
2699
+
2700
+ *Effects:* Equivalent to:
2701
+ `return `*`iterator`*`(addressof(*`*`value_`*`));`
2702
+
2703
+ ``` cpp
2704
+ constexpr iterator end() const requires (!same_as<Bound, unreachable_sentinel_t>);
2705
+ ```
2706
+
2707
+ *Effects:* Equivalent to:
2708
+ `return `*`iterator`*`(addressof(*`*`value_`*`), `*`bound_`*`);`
2709
+
2710
+ ``` cpp
2711
+ constexpr unreachable_sentinel_t end() const noexcept;
2712
+ ```
2713
+
2714
+ *Effects:* Equivalent to: `return unreachable_sentinel;`
2715
+
2716
+ ``` cpp
2717
+ constexpr auto size() const requires (!same_as<Bound, unreachable_sentinel_t>);
2718
+ ```
2719
+
2720
+ *Effects:* Equivalent to: `return `*`to-unsigned-like`*`(`*`bound_`*`);`
2721
+
2722
+ #### Class `repeat_view::iterator` <a id="range.repeat.iterator">[[range.repeat.iterator]]</a>
2723
+
2724
+ ``` cpp
2725
+ namespace std::ranges {
2726
+ template<move_constructible T, semiregular Bound>
2727
+ requires (is_object_v<T> && same_as<T, remove_cv_t<T>> &&
2728
+ (integer-like-with-usable-difference-type<Bound> ||
2729
+ same_as<Bound, unreachable_sentinel_t>))
2730
+ class repeat_view<T, Bound>::iterator {
2731
+ private:
2732
+ using index-type = // exposition only
2733
+ conditional_t<same_as<Bound, unreachable_sentinel_t>, ptrdiff_t, Bound>;
2734
+ const T* value_ = nullptr; // exposition only
2735
+ index-type current_ = index-type(); // exposition only
2736
+
2737
+ constexpr explicit iterator(const T* value, index-type b = index-type()); // exposition only
2738
+
2739
+ public:
2740
+ using iterator_concept = random_access_iterator_tag;
2741
+ using iterator_category = random_access_iterator_tag;
2742
+ using value_type = T;
2743
+ using difference_type = see below;
2744
+
2745
+ iterator() = default;
2746
+
2747
+ constexpr const T& operator*() const noexcept;
2748
+
2749
+ constexpr iterator& operator++();
2750
+ constexpr iterator operator++(int);
2751
+
2752
+ constexpr iterator& operator--();
2753
+ constexpr iterator operator--(int);
2754
+
2755
+ constexpr iterator& operator+=(difference_type n);
2756
+ constexpr iterator& operator-=(difference_type n);
2757
+ constexpr const T& operator[](difference_type n) const noexcept;
2758
+
2759
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
2760
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y);
2761
+
2762
+ friend constexpr iterator operator+(iterator i, difference_type n);
2763
+ friend constexpr iterator operator+(difference_type n, iterator i);
2764
+
2765
+ friend constexpr iterator operator-(iterator i, difference_type n);
2766
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y);
2767
+ };
2768
+ }
2769
+ ```
2770
+
2771
+ If `is-signed-integer-like<index-type>` is `true`, the member
2772
+ *typedef-name* `difference_type` denotes *`index-type`*. Otherwise, it
2773
+ denotes `IOTA-DIFF-T(index-type)` [[range.iota.view]].
2774
+
2775
+ ``` cpp
2776
+ constexpr explicit iterator(const T* value, index-type b = index-type());
2777
+ ```
2778
+
2779
+ *Preconditions:* If `Bound` is not `unreachable_sentinel_t`, `b` ≥ 0.
2780
+
2781
+ *Effects:* Initializes *value\_* with `value` and *current\_* with `b`.
2782
+
2783
+ ``` cpp
2784
+ constexpr const T& operator*() const noexcept;
2785
+ ```
2786
+
2787
+ *Effects:* Equivalent to: `return *`*`value_`*`;`
2788
+
2789
+ ``` cpp
2790
+ constexpr iterator& operator++();
2791
+ ```
2792
+
2793
+ *Effects:* Equivalent to:
2794
+
2795
+ ``` cpp
2796
+ ++current_;
2797
+ return *this;
2798
+ ```
2799
+
2800
+ ``` cpp
2801
+ constexpr iterator operator++(int);
2802
+ ```
2803
+
2804
+ *Effects:* Equivalent to:
2805
+
2806
+ ``` cpp
2807
+ auto tmp = *this;
2808
+ ++*this;
2809
+ return tmp;
2810
+ ```
2811
+
2812
+ ``` cpp
2813
+ constexpr iterator& operator--();
2814
+ ```
2815
+
2816
+ *Preconditions:* If `Bound` is not `unreachable_sentinel_t`,
2817
+ current_ > 0.
2818
+
2819
+ *Effects:* Equivalent to:
2820
+
2821
+ ``` cpp
2822
+ --current_;
2823
+ return *this;
2824
+ ```
2825
+
2826
+ ``` cpp
2827
+ constexpr iterator operator--(int);
2828
+ ```
2829
+
2830
+ *Effects:* Equivalent to:
2831
+
2832
+ ``` cpp
2833
+ auto tmp = *this;
2834
+ --*this;
2835
+ return tmp;
2836
+ ```
2837
+
2838
+ ``` cpp
2839
+ constexpr iterator& operator+=(difference_type n);
2840
+ ```
2841
+
2842
+ *Preconditions:* If `Bound` is not `unreachable_sentinel_t`,
2843
+ current_ + `n` ≥ 0.
2844
+
2845
+ *Effects:* Equivalent to:
2846
+
2847
+ ``` cpp
2848
+ current_ += n;
2849
+ return *this;
2850
+ ```
2851
+
2852
+ ``` cpp
2853
+ constexpr iterator& operator-=(difference_type n);
2854
+ ```
2855
+
2856
+ *Preconditions:* If `Bound` is not `unreachable_sentinel_t`,
2857
+ current_ - `n` ≥ 0.
2858
+
2859
+ *Effects:* Equivalent to:
2860
+
2861
+ ``` cpp
2862
+ current_ -= n;
2863
+ return *this;
2864
+ ```
2865
+
2866
+ ``` cpp
2867
+ constexpr const T& operator[](difference_type n) const noexcept;
2868
+ ```
2869
+
2870
+ *Effects:* Equivalent to: `return *(*this + n);`
2871
+
2872
+ ``` cpp
2873
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
2874
+ ```
2875
+
2876
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
2877
+
2878
+ ``` cpp
2879
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y);
2880
+ ```
2881
+
2882
+ *Effects:* Equivalent to:
2883
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
2884
+
2885
+ ``` cpp
2886
+ friend constexpr iterator operator+(iterator i, difference_type n);
2887
+ friend constexpr iterator operator+(difference_type n, iterator i);
2888
+ ```
2889
+
2890
+ *Effects:* Equivalent to:
2891
+
2892
+ ``` cpp
2893
+ i += n;
2894
+ return i;
2895
+ ```
2896
+
2897
+ ``` cpp
2898
+ friend constexpr iterator operator-(iterator i, difference_type n);
2899
+ ```
2900
+
2901
+ *Effects:* Equivalent to:
2902
+
2903
+ ``` cpp
2904
+ i -= n;
2905
+ return i;
2906
+ ```
2907
+
2908
+ ``` cpp
2909
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y);
2910
+ ```
2911
+
2912
+ *Effects:* Equivalent to:
2913
+
2914
+ ``` cpp
2915
+ return static_cast<difference_type>(x.current_) - static_cast<difference_type>(y.current_);
2916
+ ```
2917
+
2918
  ### Istream view <a id="range.istream">[[range.istream]]</a>
2919
 
2920
  #### Overview <a id="range.istream.overview">[[range.istream.overview]]</a>
2921
 
2922
  `basic_istream_view` models `input_range` and reads (using `operator>>`)
2923
  successive elements from its corresponding input stream.
2924
 
2925
+ The name `views::istream<T>` denotes a customization point object
2926
+ [[customization.point.object]]. Given a type `T` and a subexpression `E`
2927
+ of type `U`, if `U` models
2928
+ `derived_from<basic_istream<typename U::char_type,
2929
+ typename U::traits_type>>`, then the expression `views::istream<T>(E)`
2930
+ is expression-equivalent to
2931
+ `basic_istream_view<T, typename U::char_type,
2932
+ typename U::traits_type>(E)`; otherwise, `views::istream<T>(E)` is
2933
+ ill-formed.
2934
+
2935
  [*Example 1*:
2936
 
2937
  ``` cpp
2938
  auto ints = istringstream{"0 1 2 3 4"};
2939
+ ranges::copy(views::istream<int>(ints), ostream_iterator<int>{cout, "-"});
2940
  // prints 0-1-2-3-4-
2941
  ```
2942
 
2943
  — *end example*]
2944
 
 
2950
  concept stream-extractable = // exposition only
2951
  requires(basic_istream<CharT, Traits>& is, Val& t) {
2952
  is >> t;
2953
  };
2954
 
2955
+ template<movable Val, class CharT, class Traits = char_traits<CharT>>
2956
  requires default_initializable<Val> &&
2957
  stream-extractable<Val, CharT, Traits>
2958
  class basic_istream_view : public view_interface<basic_istream_view<Val, CharT, Traits>> {
2959
  public:
 
2960
  constexpr explicit basic_istream_view(basic_istream<CharT, Traits>& stream);
2961
 
2962
+ constexpr auto begin() {
2963
+ *stream_ >> value_;
 
 
 
2964
  return iterator{*this};
2965
  }
2966
 
2967
  constexpr default_sentinel_t end() const noexcept;
2968
 
2969
  private:
2970
+ // [range.istream.iterator], class basic_istream_view::iterator
2971
  struct iterator; // exposition only
2972
+ basic_istream<CharT, Traits>* stream_; // exposition only
2973
+ Val value_ = Val(); // exposition only
2974
  };
2975
  }
2976
  ```
2977
 
2978
  ``` cpp
 
2985
  constexpr default_sentinel_t end() const noexcept;
2986
  ```
2987
 
2988
  *Effects:* Equivalent to: `return default_sentinel;`
2989
 
2990
+ #### Class `basic_istream_view::iterator` <a id="range.istream.iterator">[[range.istream.iterator]]</a>
 
 
 
 
 
 
 
 
2991
 
2992
  ``` cpp
2993
  namespace std::ranges {
2994
  template<movable Val, class CharT, class Traits>
2995
  requires default_initializable<Val> &&
2996
  stream-extractable<Val, CharT, Traits>
2997
+ class basic_istream_view<Val, CharT, Traits>::iterator {
2998
  public:
2999
  using iterator_concept = input_iterator_tag;
3000
  using difference_type = ptrdiff_t;
3001
  using value_type = Val;
3002
 
 
3003
  constexpr explicit iterator(basic_istream_view& parent) noexcept;
3004
 
3005
  iterator(const iterator&) = delete;
3006
  iterator(iterator&&) = default;
3007
 
 
3014
  Val& operator*() const;
3015
 
3016
  friend bool operator==(const iterator& x, default_sentinel_t);
3017
 
3018
  private:
3019
+ basic_istream_view* parent_; // exposition only
3020
  };
3021
  }
3022
  ```
3023
 
3024
  ``` cpp
 
3029
 
3030
  ``` cpp
3031
  iterator& operator++();
3032
  ```
3033
 
 
 
3034
  *Effects:* Equivalent to:
3035
 
3036
  ``` cpp
3037
+ *parent_->stream_ >> parent_->value_;
3038
  return *this;
3039
  ```
3040
 
3041
  ``` cpp
3042
  void operator++(int);
3043
  ```
3044
 
 
 
3045
  *Effects:* Equivalent to `++*this`.
3046
 
3047
  ``` cpp
3048
  Val& operator*() const;
3049
  ```
3050
 
3051
+ *Effects:* Equivalent to: `return `*`parent_`*`->`*`value_`*`;`
 
 
3052
 
3053
  ``` cpp
3054
  friend bool operator==(const iterator& x, default_sentinel_t);
3055
  ```
3056
 
3057
+ *Effects:* Equivalent to: `return !*x.`*`parent_`*`->`*`stream_`*`;`
 
3058
 
3059
  ## Range adaptors <a id="range.adaptors">[[range.adaptors]]</a>
3060
 
3061
+ ### General <a id="range.adaptors.general">[[range.adaptors.general]]</a>
3062
+
3063
+ Subclause [[range.adaptors]] defines *range adaptors*, which are
3064
+ utilities that transform a range into a view with custom behaviors.
3065
+ These adaptors can be chained to create pipelines of range
3066
+ transformations that evaluate lazily as the resulting view is iterated.
3067
 
3068
  Range adaptors are declared in namespace `std::ranges::views`.
3069
 
3070
  The bitwise operator is overloaded for the purpose of creating adaptor
3071
  chain pipelines. The adaptors also support function call syntax with
 
3076
  ``` cpp
3077
  vector<int> ints{0,1,2,3,4,5};
3078
  auto even = [](int i) { return 0 == i % 2; };
3079
  auto square = [](int i) { return i * i; };
3080
  for (int i : ints | views::filter(even) | views::transform(square)) {
3081
+ cout << i << ' '; // prints 0 4 16
3082
  }
3083
  assert(ranges::equal(ints | views::filter(even), views::filter(ints, even)));
3084
  ```
3085
 
3086
  — *end example*]
3087
 
3088
  ### Range adaptor objects <a id="range.adaptor.object">[[range.adaptor.object]]</a>
3089
 
3090
  A *range adaptor closure object* is a unary function object that accepts
3091
+ a range argument. For a range adaptor closure object `C` and an
3092
+ expression `R` such that `decltype((R))` models `range`, the following
3093
+ expressions are equivalent:
 
3094
 
3095
  ``` cpp
3096
  C(R)
3097
  R | C
3098
  ```
3099
 
3100
  Given an additional range adaptor closure object `D`, the expression
3101
+ `C | D` produces another range adaptor closure object `E`. `E` is a
3102
+ perfect forwarding call wrapper [[term.perfect.forwarding.call.wrapper]]
3103
+ with the following properties:
3104
 
3105
+ - Its target object is an object `d` of type `decay_t<decltype((D))>`
3106
+ direct-non-list-initialized with `D`.
3107
+ - It has one bound argument entity, an object `c` of type
3108
+ `decay_t<decltype((C))>` direct-non-list-initialized with `C`.
3109
+ - Its call pattern is `d(c(arg))`, where `arg` is the argument used in a
3110
+ function call expression of `E`.
3111
+
3112
+ The expression `C | D` is well-formed if and only if the initializations
3113
+ of the state entities of `E` are all well-formed.
3114
+
3115
+ Given an object `t` of type `T`, where
3116
+
3117
+ - `t` is a unary function object that accepts a range argument,
3118
+ - `T` models `derived_from<range_adaptor_closure<T>>`,
3119
+ - `T` has no other base classes of type `range_adaptor_closure<U>` for
3120
+ any other type `U`, and
3121
+ - `T` does not model `range`
3122
+
3123
+ then the implementation ensures that `t` is a range adaptor closure
3124
+ object.
3125
+
3126
+ The template parameter `D` for `range_adaptor_closure` may be an
3127
+ incomplete type. If an expression of type cv `D` is used as an operand
3128
+ to the `|` operator, `D` shall be complete and model
3129
+ `derived_from<range_adaptor_closure<D>>`. The behavior of an expression
3130
+ involving an object of type cv `D` as an operand to the `|` operator is
3131
+ undefined if overload resolution selects a program-defined `operator|`
3132
+ function.
3133
+
3134
+ If an expression of type cv `U` is used as an operand to the `|`
3135
+ operator, where `U` has a base class of type `range_adaptor_closure<T>`
3136
+ for some type `T` other than `U`, the behavior is undefined.
3137
+
3138
+ The behavior of a program that adds a specialization for
3139
+ `range_adaptor_closure` is undefined.
3140
 
3141
  A *range adaptor object* is a customization point object
3142
  [[customization.point.object]] that accepts a `viewable_range` as its
3143
+ first argument and returns a view.
3144
 
3145
  If a range adaptor object accepts only one argument, then it is a range
3146
  adaptor closure object.
3147
 
3148
+ If a range adaptor object `adaptor` accepts more than one argument, then
3149
+ let `range` be an expression such that `decltype((range))` models
3150
+ `viewable_range`, let `args...` be arguments such that
3151
+ `adaptor(range, args...)` is a well-formed expression as specified in
3152
+ the rest of subclause  [[range.adaptors]], and let `BoundArgs` be a pack
3153
+ that denotes `decay_t<decltype((args))>...`. The expression
3154
+ `adaptor(args...)` produces a range adaptor closure object `f` that is a
3155
+ perfect forwarding call wrapper [[term.perfect.forwarding.call.wrapper]]
3156
+ with the following properties:
3157
 
3158
+ - Its target object is a copy of `adaptor`.
3159
+ - Its bound argument entities `bound_args` consist of objects of types
3160
+ `BoundArgs...` direct-non-list-initialized with
3161
+ `std::forward<decltype((args))>(args)...`, respectively.
3162
+ - Its call pattern is `adaptor(r, bound_args...)`, where `r` is the
3163
+ argument used in a function call expression of `f`.
3164
 
3165
+ The expression `adaptor(args...)` is well-formed if and only if the
3166
+ initialization of the bound argument entities of the result, as
3167
+ specified above, are all well-formed.
3168
 
3169
+ ### Movable wrapper <a id="range.move.wrap">[[range.move.wrap]]</a>
3170
 
3171
  Many types in this subclause are specified in terms of an
3172
+ exposition-only class template *`movable-box`*. `movable-box<T>` behaves
3173
+ exactly like `optional<T>` with the following differences:
3174
 
3175
+ - `movable-box<T>` constrains its type parameter `T` with
3176
+ `move_constructible<T> && is_object_v<T>`.
3177
+ - The default constructor of `movable-box<T>` is equivalent to:
 
3178
  ``` cpp
3179
+ constexpr movable-box() noexcept(is_nothrow_default_constructible_v<T>)
3180
+ requires default_initializable<T>
3181
+ : movable-box{in_place} {}
3182
  ```
3183
+ - If `copyable<T>` is not modeled, the copy assignment operator is
3184
+ equivalent to:
3185
  ``` cpp
3186
+ constexpr movable-box& operator=(const movable-box& that)
3187
  noexcept(is_nothrow_copy_constructible_v<T>)
3188
+ requires copy_constructible<T> {
3189
+ if (this != addressof(that)) {
3190
  if (that) emplace(*that);
3191
  else reset();
3192
+ }
3193
  return *this;
3194
  }
3195
  ```
3196
+ - If `movable<T>` is not modeled, the move assignment operator is
3197
+ equivalent to:
3198
  ``` cpp
3199
+ constexpr movable-box& operator=(movable-box&& that)
3200
+ noexcept(is_nothrow_move_constructible_v<T>) {
3201
+ if (this != addressof(that)) {
3202
  if (that) emplace(std::move(*that));
3203
  else reset();
3204
+ }
3205
  return *this;
3206
  }
3207
  ```
3208
 
3209
+ *Recommended practice:*
3210
+
3211
+ - If `copy_constructible<T>` is `true`, `movable-box<T>` should store
3212
+ only a `T` if either `T` models `copyable`, or
3213
+ `is_nothrow_move_constructible_v<T> && is_nothrow_copy_constructible_v<T>`
3214
+ is `true`.
3215
+ - Otherwise, `movable-box<T>` should store only a `T` if either `T`
3216
+ models `movable` or `is_nothrow_move_constructible_v<T>` is `true`.
3217
+
3218
+ ### Non-propagating cache <a id="range.nonprop.cache">[[range.nonprop.cache]]</a>
3219
+
3220
+ Some types in subclause [[range.adaptors]] are specified in terms of an
3221
+ exposition-only class template *`non-propagating-{}cache`*.
3222
+ `non-propagating-cache<T>` behaves exactly like `optional<T>` with the
3223
+ following differences:
3224
+
3225
+ - `non-propagating-cache<T>` constrains its type parameter `T` with
3226
+ `is_object_v<T>`.
3227
+ - The copy constructor is equivalent to:
3228
+ ``` cpp
3229
+ constexpr non-propagating-cache(const non-propagating-cache&) noexcept {}
3230
+ ```
3231
+ - The move constructor is equivalent to:
3232
+ ``` cpp
3233
+ constexpr non-propagating-cache(non-propagating-cache&& other) noexcept {
3234
+ other.reset();
3235
+ }
3236
+ ```
3237
+ - The copy assignment operator is equivalent to:
3238
+ ``` cpp
3239
+ constexpr non-propagating-cache& operator=(const non-propagating-cache& other) noexcept {
3240
+ if (addressof(other) != this)
3241
+ reset();
3242
+ return *this;
3243
+ }
3244
+ ```
3245
+ - The move assignment operator is equivalent to:
3246
+ ``` cpp
3247
+ constexpr non-propagating-cache& operator=(non-propagating-cache&& other) noexcept {
3248
+ reset();
3249
+ other.reset();
3250
+ return *this;
3251
+ }
3252
+ ```
3253
+ - `non-propagating-cache<T>` has an additional member function template
3254
+ specified as follows:
3255
+ ``` cpp
3256
+ template<class I>
3257
+ constexpr T& emplace-deref(const I& i); // exposition only
3258
+ ```
3259
+
3260
+ *Mandates:* The declaration `T t(*i);` is well-formed for some
3261
+ invented variable `t`.
3262
+ \[*Note 1*: If `*i` is a prvalue of type cv `T`, there is no
3263
+ requirement that it is movable [[dcl.init.general]]. — *end note*]
3264
+ *Effects:* Calls `reset()`. Then direct-non-list-initializes the
3265
+ contained value with `*i`.
3266
+ *Ensures:* `*this` contains a value.
3267
+ *Returns:* A reference to the new contained value.
3268
+ *Throws:* Any exception thrown by the initialization of the contained
3269
+ value.
3270
+ *Remarks:* If an exception is thrown during the initialization of `T`,
3271
+ `*this` does not contain a value, and the previous value (if any) has
3272
+ been destroyed.
3273
+
3274
+ [*Note 1*: *`non-propagating-cache`* enables an input view to
3275
+ temporarily cache values as it is iterated over. — *end note*]
3276
+
3277
+ ### Range adaptor helpers <a id="range.adaptor.helpers">[[range.adaptor.helpers]]</a>
3278
+
3279
+ ``` cpp
3280
+ namespace std::ranges {
3281
+ template<class F, class Tuple>
3282
+ constexpr auto tuple-transform(F&& f, Tuple&& t) { // exposition only
3283
+ return apply([&]<class... Ts>(Ts&&... elements) {
3284
+ return tuple<invoke_result_t<F&, Ts>...>(invoke(f, std::forward<Ts>(elements))...);
3285
+ }, std::forward<Tuple>(t));
3286
+ }
3287
+
3288
+ template<class F, class Tuple>
3289
+ constexpr void tuple-for-each(F&& f, Tuple&& t) { // exposition only
3290
+ apply([&]<class... Ts>(Ts&&... elements) {
3291
+ (static_cast<void>(invoke(f, std::forward<Ts>(elements))), ...);
3292
+ }, std::forward<Tuple>(t));
3293
+ }
3294
+
3295
+ template<class T>
3296
+ constexpr T& as-lvalue(T&& t) { // exposition only
3297
+ return static_cast<T&>(t);
3298
+ }
3299
+ }
3300
+ ```
3301
+
3302
  ### All view <a id="range.all">[[range.all]]</a>
3303
 
3304
+ #### General <a id="range.all.general">[[range.all.general]]</a>
3305
+
3306
+ `views::all` returns a view that includes all elements of its range
3307
  argument.
3308
 
3309
  The name `views::all` denotes a range adaptor object
3310
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
3311
  `views::all(E)` is expression-equivalent to:
3312
 
3313
  - `decay-copy(E)` if the decayed type of `E` models `view`.
3314
  - Otherwise, `ref_view{E}` if that expression is well-formed.
3315
+ - Otherwise, `owning_view{E}`.
3316
 
3317
  #### Class template `ref_view` <a id="range.ref.view">[[range.ref.view]]</a>
3318
 
3319
+ `ref_view` is a view of the elements of some other range.
3320
 
3321
  ``` cpp
3322
  namespace std::ranges {
3323
  template<range R>
3324
  requires is_object_v<R>
3325
  class ref_view : public view_interface<ref_view<R>> {
3326
  private:
3327
+ R* r_; // exposition only
 
 
3328
 
3329
+ public:
3330
+ template<different-from<ref_view> T>
3331
  requires see below
3332
  constexpr ref_view(T&& t);
3333
 
3334
  constexpr R& base() const { return *r_; }
3335
 
 
3344
  { return ranges::size(*r_); }
3345
 
3346
  constexpr auto data() const requires contiguous_range<R>
3347
  { return ranges::data(*r_); }
3348
  };
3349
+
3350
  template<class R>
3351
  ref_view(R&) -> ref_view<R>;
3352
  }
3353
  ```
3354
 
3355
  ``` cpp
3356
+ template<different-from<ref_view> T>
3357
  requires see below
3358
  constexpr ref_view(T&& t);
3359
  ```
3360
 
3361
+ *Effects:* Initializes *r\_* with
3362
+ `addressof(static_cast<R&>(std::forward<T>(t)))`.
3363
+
3364
  *Remarks:* Let *`FUN`* denote the exposition-only functions
3365
 
3366
  ``` cpp
3367
  void FUN(R&);
3368
  void FUN(R&&) = delete;
3369
  ```
3370
 
3371
+ The expression in the *requires-clause* is equivalent to:
3372
 
3373
  ``` cpp
3374
  convertible_to<T, R&> && requires { FUN(declval<T>()); }
3375
  ```
3376
 
3377
+ #### Class template `owning_view` <a id="range.owning.view">[[range.owning.view]]</a>
3378
+
3379
+ `owning_view` is a move-only view of the elements of some other range.
3380
+
3381
+ ``` cpp
3382
+ namespace std::ranges {
3383
+ template<range R>
3384
+ requires movable<R> && (!is-initializer-list<R>) // see [range.refinements]
3385
+ class owning_view : public view_interface<owning_view<R>> {
3386
+ private:
3387
+ R r_ = R(); // exposition only
3388
+
3389
+ public:
3390
+ owning_view() requires default_initializable<R> = default;
3391
+ constexpr owning_view(R&& t);
3392
+
3393
+ owning_view(owning_view&&) = default;
3394
+ owning_view& operator=(owning_view&&) = default;
3395
+
3396
+ constexpr R& base() & noexcept { return r_; }
3397
+ constexpr const R& base() const & noexcept { return r_; }
3398
+ constexpr R&& base() && noexcept { return std::move(r_); }
3399
+ constexpr const R&& base() const && noexcept { return std::move(r_); }
3400
+
3401
+ constexpr iterator_t<R> begin() { return ranges::begin(r_); }
3402
+ constexpr sentinel_t<R> end() { return ranges::end(r_); }
3403
+
3404
+ constexpr auto begin() const requires range<const R>
3405
+ { return ranges::begin(r_); }
3406
+ constexpr auto end() const requires range<const R>
3407
+ { return ranges::end(r_); }
3408
+
3409
+ constexpr bool empty() requires requires { ranges::empty(r_); }
3410
+ { return ranges::empty(r_); }
3411
+ constexpr bool empty() const requires requires { ranges::empty(r_); }
3412
+ { return ranges::empty(r_); }
3413
+
3414
+ constexpr auto size() requires sized_range<R>
3415
+ { return ranges::size(r_); }
3416
+ constexpr auto size() const requires sized_range<const R>
3417
+ { return ranges::size(r_); }
3418
+
3419
+ constexpr auto data() requires contiguous_range<R>
3420
+ { return ranges::data(r_); }
3421
+ constexpr auto data() const requires contiguous_range<const R>
3422
+ { return ranges::data(r_); }
3423
+ };
3424
+ }
3425
+ ```
3426
+
3427
+ ``` cpp
3428
+ constexpr owning_view(R&& t);
3429
+ ```
3430
+
3431
+ *Effects:* Initializes *r\_* with `std::move(t)`.
3432
+
3433
+ ### As rvalue view <a id="range.as.rvalue">[[range.as.rvalue]]</a>
3434
+
3435
+ #### Overview <a id="range.as.rvalue.overview">[[range.as.rvalue.overview]]</a>
3436
+
3437
+ `as_rvalue_view` presents a view of an underlying sequence with the same
3438
+ behavior as the underlying sequence except that its elements are
3439
+ rvalues. Some generic algorithms can be called with an `as_rvalue_view`
3440
+ to replace copying with moving.
3441
+
3442
+ The name `views::as_rvalue` denotes a range adaptor object
3443
+ [[range.adaptor.object]]. Let `E` be an expression and let `T` be
3444
+ `decltype((E))`. The expression `views::as_rvalue(E)` is
3445
+ expression-equivalent to:
3446
+
3447
+ - `views::all(E)` if
3448
+ `same_as<range_rvalue_reference_t<T>, range_reference_t<T>>` is
3449
+ `true`.
3450
+ - Otherwise, `as_rvalue_view(E)`.
3451
+
3452
+ [*Example 1*:
3453
+
3454
+ ``` cpp
3455
+ vector<string> words = {"the", "quick", "brown", "fox", "ate", "a", "pterodactyl"};
3456
+ vector<string> new_words;
3457
+ ranges::copy(words | views::as_rvalue, back_inserter(new_words));
3458
+ // moves each string from words into new_words
3459
+ ```
3460
+
3461
+ — *end example*]
3462
+
3463
+ #### Class template `as_rvalue_view` <a id="range.as.rvalue.view">[[range.as.rvalue.view]]</a>
3464
+
3465
+ ``` cpp
3466
+ namespace std::ranges {
3467
+ template<view V>
3468
+ requires input_range<V>
3469
+ class as_rvalue_view : public view_interface<as_rvalue_view<V>> {
3470
+ V base_ = V(); // exposition only
3471
+
3472
+ public:
3473
+ as_rvalue_view() requires default_initializable<V> = default;
3474
+ constexpr explicit as_rvalue_view(V base);
3475
+
3476
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
3477
+ constexpr V base() && { return std::move(base_); }
3478
+
3479
+ constexpr auto begin() requires (!simple-view<V>)
3480
+ { return move_iterator(ranges::begin(base_)); }
3481
+ constexpr auto begin() const requires range<const V>
3482
+ { return move_iterator(ranges::begin(base_)); }
3483
+
3484
+ constexpr auto end() requires (!simple-view<V>) {
3485
+ if constexpr (common_range<V>) {
3486
+ return move_iterator(ranges::end(base_));
3487
+ } else {
3488
+ return move_sentinel(ranges::end(base_));
3489
+ }
3490
+ }
3491
+ constexpr auto end() const requires range<const V> {
3492
+ if constexpr (common_range<const V>) {
3493
+ return move_iterator(ranges::end(base_));
3494
+ } else {
3495
+ return move_sentinel(ranges::end(base_));
3496
+ }
3497
+ }
3498
+
3499
+ constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
3500
+ constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
3501
+ };
3502
+
3503
+ template<class R>
3504
+ as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>;
3505
+ }
3506
+ ```
3507
+
3508
+ ``` cpp
3509
+ constexpr explicit as_rvalue_view(V base);
3510
+ ```
3511
+
3512
+ *Effects:* Initializes *base\_* with `std::move(base)`.
3513
 
3514
  ### Filter view <a id="range.filter">[[range.filter]]</a>
3515
 
3516
  #### Overview <a id="range.filter.overview">[[range.filter.overview]]</a>
3517
 
3518
+ `filter_view` presents a view of the elements of an underlying sequence
3519
+ that satisfy a predicate.
3520
 
3521
  The name `views::filter` denotes a range adaptor object
3522
  [[range.adaptor.object]]. Given subexpressions `E` and `P`, the
3523
  expression `views::filter(E, P)` is expression-equivalent to
3524
+ `filter_view(E, P)`.
3525
 
3526
  [*Example 1*:
3527
 
3528
  ``` cpp
3529
  vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
3530
+ auto evens = views::filter(is, [](int i) { return 0 == i % 2; });
3531
  for (int i : evens)
3532
+ cout << i << ' '; // prints 0 2 4 6
3533
  ```
3534
 
3535
  — *end example*]
3536
 
3537
  #### Class template `filter_view` <a id="range.filter.view">[[range.filter.view]]</a>
 
3541
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
3542
  requires view<V> && is_object_v<Pred>
3543
  class filter_view : public view_interface<filter_view<V, Pred>> {
3544
  private:
3545
  V base_ = V(); // exposition only
3546
+ movable-box<Pred> pred_; // exposition only
3547
 
3548
  // [range.filter.iterator], class filter_view::iterator
3549
  class iterator; // exposition only
3550
+
3551
  // [range.filter.sentinel], class filter_view::sentinel
3552
  class sentinel; // exposition only
3553
 
3554
  public:
3555
+ filter_view() requires default_initializable<V> && default_initializable<Pred> = default;
3556
+ constexpr explicit filter_view(V base, Pred pred);
3557
 
3558
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3559
  constexpr V base() && { return std::move(base_); }
3560
 
3561
  constexpr const Pred& pred() const;
 
3573
  filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;
3574
  }
3575
  ```
3576
 
3577
  ``` cpp
3578
+ constexpr explicit filter_view(V base, Pred pred);
3579
  ```
3580
 
3581
  *Effects:* Initializes *base\_* with `std::move(base)` and initializes
3582
  *pred\_* with `std::move(pred)`.
3583
 
 
3589
 
3590
  ``` cpp
3591
  constexpr iterator begin();
3592
  ```
3593
 
3594
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
3595
 
3596
  *Returns:* `{*this, ranges::find_if(`*`base_`*`, ref(*`*`pred_`*`))}`.
3597
 
3598
  *Remarks:* In order to provide the amortized constant time complexity
3599
  required by the `range` concept when `filter_view` models
 
3608
  requires view<V> && is_object_v<Pred>
3609
  class filter_view<V, Pred>::iterator {
3610
  private:
3611
  iterator_t<V> current_ = iterator_t<V>(); // exposition only
3612
  filter_view* parent_ = nullptr; // exposition only
3613
+
3614
  public:
3615
+ using iterator_concept = see belownc;
3616
+ using iterator_category = see belownc; // not always present
3617
  using value_type = range_value_t<V>;
3618
  using difference_type = range_difference_t<V>;
3619
 
3620
+ iterator() requires default_initializable<iterator_t<V>> = default;
3621
  constexpr iterator(filter_view& parent, iterator_t<V> current);
3622
 
3623
+ constexpr const iterator_t<V>& base() const & noexcept;
 
3624
  constexpr iterator_t<V> base() &&;
3625
  constexpr range_reference_t<V> operator*() const;
3626
  constexpr iterator_t<V> operator->() const
3627
  requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;
3628
 
 
3636
  friend constexpr bool operator==(const iterator& x, const iterator& y)
3637
  requires equality_comparable<iterator_t<V>>;
3638
 
3639
  friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
3640
  noexcept(noexcept(ranges::iter_move(i.current_)));
3641
+
3642
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
3643
  noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
3644
  requires indirectly_swappable<iterator_t<V>>;
3645
  };
3646
  }
 
3656
  `bidirectional_iterator_tag`.
3657
  - Otherwise, if `V` models `forward_range`, then `iterator_concept`
3658
  denotes `forward_iterator_tag`.
3659
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
3660
 
3661
+ The member *typedef-name* `iterator_category` is defined if and only if
3662
+ `V` models `forward_range`. In that case, `iterator::iterator_category`
3663
+ is defined as follows:
3664
 
3665
  - Let `C` denote the type
3666
  `iterator_traits<iterator_t<V>>::iterator_category`.
3667
  - If `C` models `derived_from<bidirectional_iterator_tag>`, then
3668
  `iterator_category` denotes `bidirectional_iterator_tag`.
 
3676
 
3677
  *Effects:* Initializes *current\_* with `std::move(current)` and
3678
  *parent\_* with `addressof(parent)`.
3679
 
3680
  ``` cpp
3681
+ constexpr const iterator_t<V>& base() const & noexcept;
 
3682
  ```
3683
 
3684
  *Effects:* Equivalent to: `return `*`current_`*`;`
3685
 
3686
  ``` cpp
3687
  constexpr iterator_t<V> base() &&;
3688
  ```
3689
 
3690
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
3691
 
3692
  ``` cpp
3693
  constexpr range_reference_t<V> operator*() const;
3694
  ```
3695
 
 
3787
  template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred>
3788
  requires view<V> && is_object_v<Pred>
3789
  class filter_view<V, Pred>::sentinel {
3790
  private:
3791
  sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
3792
+
3793
  public:
3794
  sentinel() = default;
3795
  constexpr explicit sentinel(filter_view& parent);
3796
 
3797
  constexpr sentinel_t<V> base() const;
 
3821
 
3822
  ### Transform view <a id="range.transform">[[range.transform]]</a>
3823
 
3824
  #### Overview <a id="range.transform.overview">[[range.transform.overview]]</a>
3825
 
3826
+ `transform_view` presents a view of an underlying sequence after
3827
  applying a transformation function to each element.
3828
 
3829
  The name `views::transform` denotes a range adaptor object
3830
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
3831
  expression `views::transform(E, F)` is expression-equivalent to
3832
+ `transform_view(E, F)`.
3833
 
3834
  [*Example 1*:
3835
 
3836
  ``` cpp
3837
  vector<int> is{ 0, 1, 2, 3, 4 };
3838
+ auto squares = views::transform(is, [](int i) { return i * i; });
3839
  for (int i : squares)
3840
+ cout << i << ' '; // prints 0 1 4 9 16
3841
  ```
3842
 
3843
  — *end example*]
3844
 
3845
  #### Class template `transform_view` <a id="range.transform.view">[[range.transform.view]]</a>
3846
 
3847
  ``` cpp
3848
  namespace std::ranges {
3849
+ template<input_range V, move_constructible F>
3850
  requires view<V> && is_object_v<F> &&
3851
  regular_invocable<F&, range_reference_t<V>> &&
3852
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
3853
  class transform_view : public view_interface<transform_view<V, F>> {
3854
  private:
3855
  // [range.transform.iterator], class template transform_view::iterator
3856
  template<bool> struct iterator; // exposition only
3857
+
3858
  // [range.transform.sentinel], class template transform_view::sentinel
3859
  template<bool> struct sentinel; // exposition only
3860
 
3861
  V base_ = V(); // exposition only
3862
+ movable-box<F> fun_; // exposition only
3863
 
3864
  public:
3865
+ transform_view() requires default_initializable<V> && default_initializable<F> = default;
3866
+ constexpr explicit transform_view(V base, F fun);
3867
 
3868
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3869
  constexpr V base() && { return std::move(base_); }
3870
 
3871
  constexpr iterator<false> begin();
 
3891
  transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
3892
  }
3893
  ```
3894
 
3895
  ``` cpp
3896
+ constexpr explicit transform_view(V base, F fun);
3897
  ```
3898
 
3899
  *Effects:* Initializes *base\_* with `std::move(base)` and *fun\_* with
3900
  `std::move(fun)`.
3901
 
 
3967
 
3968
  #### Class template `transform_view::iterator` <a id="range.transform.iterator">[[range.transform.iterator]]</a>
3969
 
3970
  ``` cpp
3971
  namespace std::ranges {
3972
+ template<input_range V, move_constructible F>
3973
  requires view<V> && is_object_v<F> &&
3974
  regular_invocable<F&, range_reference_t<V>> &&
3975
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
3976
  template<bool Const>
3977
  class transform_view<V, F>::iterator {
3978
  private:
3979
+ using Parent = maybe-const<Const, transform_view>; // exposition only
3980
+ using Base = maybe-const<Const, V>; // exposition only
3981
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
 
 
 
3982
  Parent* parent_ = nullptr; // exposition only
3983
+
3984
  public:
3985
+ using iterator_concept = see belownc;
3986
+ using iterator_category = see belownc; // not always present
3987
  using value_type =
3988
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>>;
3989
  using difference_type = range_difference_t<Base>;
3990
 
3991
+ iterator() requires default_initializable<iterator_t<Base>> = default;
3992
  constexpr iterator(Parent& parent, iterator_t<Base> current);
3993
  constexpr iterator(iterator<!Const> i)
3994
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
3995
 
3996
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
3997
  constexpr iterator_t<Base> base() &&;
3998
+
3999
  constexpr decltype(auto) operator*() const
4000
+ noexcept(noexcept(invoke(*parent_->fun_, *current_))) {
4001
+ return invoke(*parent_->fun_, *current_);
4002
+ }
4003
 
4004
  constexpr iterator& operator++();
4005
  constexpr void operator++(int);
4006
  constexpr iterator operator++(int) requires forward_range<Base>;
4007
 
 
4010
 
4011
  constexpr iterator& operator+=(difference_type n)
4012
  requires random_access_range<Base>;
4013
  constexpr iterator& operator-=(difference_type n)
4014
  requires random_access_range<Base>;
4015
+
4016
  constexpr decltype(auto) operator[](difference_type n) const
4017
+ requires random_access_range<Base> {
4018
+ return invoke(*parent_->fun_, current_[n]);
4019
+ }
4020
 
4021
  friend constexpr bool operator==(const iterator& x, const iterator& y)
4022
  requires equality_comparable<iterator_t<Base>>;
4023
 
4024
  friend constexpr bool operator<(const iterator& x, const iterator& y)
 
4038
  requires random_access_range<Base>;
4039
 
4040
  friend constexpr iterator operator-(iterator i, difference_type n)
4041
  requires random_access_range<Base>;
4042
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4043
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
 
 
 
 
 
 
 
 
 
 
 
 
 
4044
  };
4045
  }
4046
  ```
4047
 
4048
  `iterator::iterator_concept` is defined as follows:
4049
 
4050
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
4051
+ denotes `random_access_iterator_tag`.
4052
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
4053
  `iterator_concept` denotes `bidirectional_iterator_tag`.
4054
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
4055
  denotes `forward_iterator_tag`.
4056
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
4057
 
4058
+ The member *typedef-name* `iterator_category` is defined if and only if
4059
+ *`Base`* models `forward_range`. In that case,
4060
  `iterator::iterator_category` is defined as follows: Let `C` denote the
4061
  type `iterator_traits<iterator_t<Base>>::iterator_category`.
4062
 
4063
  - If
4064
+ `is_reference_v<invoke_result_t<maybe-const<Const, F>&, range_reference_t<Base>>>`
4065
  is `true`, then
4066
  - if `C` models `derived_from<contiguous_iterator_tag>`,
4067
  `iterator_category` denotes `random_access_iterator_tag`;
4068
  - otherwise, `iterator_category` denotes `C`.
4069
  - Otherwise, `iterator_category` denotes `input_iterator_tag`.
 
4082
 
4083
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
4084
  and *parent\_* with `i.`*`parent_`*.
4085
 
4086
  ``` cpp
4087
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
4088
  ```
4089
 
4090
  *Effects:* Equivalent to: `return `*`current_`*`;`
4091
 
4092
  ``` cpp
4093
  constexpr iterator_t<Base> base() &&;
4094
  ```
4095
 
4096
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
4097
 
4098
  ``` cpp
4099
  constexpr iterator& operator++();
4100
  ```
4101
 
 
4108
 
4109
  ``` cpp
4110
  constexpr void operator++(int);
4111
  ```
4112
 
4113
+ *Effects:* Equivalent to `++`*`current_`*.
4114
 
4115
  ``` cpp
4116
  constexpr iterator operator++(int) requires forward_range<Base>;
4117
  ```
4118
 
 
4220
  friend constexpr iterator operator+(difference_type n, iterator i)
4221
  requires random_access_range<Base>;
4222
  ```
4223
 
4224
  *Effects:* Equivalent to:
4225
+ `return `*`iterator`*`{*i.`*`parent_`*`, i.`*`current_`*` + n};`
4226
 
4227
  ``` cpp
4228
  friend constexpr iterator operator-(iterator i, difference_type n)
4229
  requires random_access_range<Base>;
4230
  ```
4231
 
4232
  *Effects:* Equivalent to:
4233
+ `return `*`iterator`*`{*i.`*`parent_`*`, i.`*`current_`*` - n};`
4234
 
4235
  ``` cpp
4236
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4237
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
4238
  ```
4239
 
4240
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
4241
 
 
 
 
 
 
 
 
 
 
4242
  #### Class template `transform_view::sentinel` <a id="range.transform.sentinel">[[range.transform.sentinel]]</a>
4243
 
4244
  ``` cpp
4245
  namespace std::ranges {
4246
+ template<input_range V, move_constructible F>
4247
  requires view<V> && is_object_v<F> &&
4248
  regular_invocable<F&, range_reference_t<V>> &&
4249
  can-reference<invoke_result_t<F&, range_reference_t<V>>>
4250
  template<bool Const>
4251
  class transform_view<V, F>::sentinel {
4252
  private:
4253
+ using Parent = maybe-const<Const, transform_view>; // exposition only
4254
+ using Base = maybe-const<Const, V>; // exposition only
 
4255
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
4256
+
4257
  public:
4258
  sentinel() = default;
4259
  constexpr explicit sentinel(sentinel_t<Base> end);
4260
  constexpr sentinel(sentinel<!Const> i)
4261
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4262
 
4263
  constexpr sentinel_t<Base> base() const;
4264
 
4265
+ template<bool OtherConst>
4266
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4267
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
4268
 
4269
+ template<bool OtherConst>
4270
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4271
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4272
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
4273
+
4274
+ template<bool OtherConst>
4275
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4276
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4277
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
4278
  };
4279
  }
4280
  ```
4281
 
4282
  ``` cpp
 
4297
  ```
4298
 
4299
  *Effects:* Equivalent to: `return `*`end_`*`;`
4300
 
4301
  ``` cpp
4302
+ template<bool OtherConst>
4303
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4304
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
4305
  ```
4306
 
4307
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
4308
 
4309
  ``` cpp
4310
+ template<bool OtherConst>
4311
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4312
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4313
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
4314
  ```
4315
 
4316
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
4317
 
4318
  ``` cpp
4319
+ template<bool OtherConst>
4320
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4321
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4322
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
4323
  ```
4324
 
4325
  *Effects:* Equivalent to: `return y.`*`end_`*` - x.`*`current_`*`;`
4326
 
4327
  ### Take view <a id="range.take">[[range.take]]</a>
4328
 
4329
  #### Overview <a id="range.take.overview">[[range.take.overview]]</a>
4330
 
4331
+ `take_view` produces a view of the first N elements from another view,
4332
+ or all the elements if the adapted view contains fewer than N.
4333
 
4334
  The name `views::take` denotes a range adaptor object
4335
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
4336
  `remove_cvref_t<decltype((E))>`, and let `D` be
4337
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
4338
  `convertible_to<D>`, `views::take(E, F)` is ill-formed. Otherwise, the
4339
  expression `views::take(E, F)` is expression-equivalent to:
4340
 
4341
+ - If `T` is a specialization of `empty_view` [[range.empty.view]], then
4342
+ `((void)F, decay-copy(E))`, except that the evaluations of `E` and `F`
4343
+ are indeterminately sequenced.
4344
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
4345
+ is a specialization of `span` [[views.span]], `basic_string_view`
4346
+ [[string.view]], or `subrange` [[range.subrange]], then
4347
+ `U(ranges::begin(E),
4348
+ ranges::begin(E) + std::min<D>(ranges::distance(E), F))`, except that
4349
+ `E` is evaluated only once, where `U` is a type determined as follows:
4350
+ - if `T` is a specialization of `span`, then `U` is
4351
+ `span<typename T::element_type>`;
4352
+ - otherwise, if `T` is a specialization of `basic_string_view`, then
4353
+ `U` is `T`;
4354
+ - otherwise, `T` is a specialization of `subrange`, and `U` is
4355
+ `subrange<iterator_t<T>>`;
4356
+ - otherwise, if `T` is a specialization of `iota_view`
4357
+ [[range.iota.view]] that models `random_access_range` and
4358
+ `sized_range`, then `iota_view(*ranges::begin(E),
4359
+ *(ranges::begin(E) + std::{}min<D>(ranges::distance(E), F)))`, except
4360
+ that `E` is evaluated only once.
4361
+ - Otherwise, if `T` is a specialization of `repeat_view`
4362
+ [[range.repeat.view]]:
4363
+ - if `T` models `sized_range`, then
4364
+ ``` cpp
4365
+ views::repeat(*E.value_, std::min<D>(ranges::distance(E), F))
4366
+ ```
4367
 
4368
+ except that `E` is evaluated only once;
4369
+ - otherwise, `views::repeat(*E.value_, static_cast<D>(F))`.
4370
+ - Otherwise, `take_view(E, F)`.
 
4371
 
4372
  [*Example 1*:
4373
 
4374
  ``` cpp
4375
  vector<int> is{0,1,2,3,4,5,6,7,8,9};
4376
+ for (int i : is | views::take(5))
4377
+ cout << i << ' '; // prints 0 1 2 3 4
 
4378
  ```
4379
 
4380
  — *end example*]
4381
 
4382
  #### Class template `take_view` <a id="range.take.view">[[range.take.view]]</a>
 
4386
  template<view V>
4387
  class take_view : public view_interface<take_view<V>> {
4388
  private:
4389
  V base_ = V(); // exposition only
4390
  range_difference_t<V> count_ = 0; // exposition only
4391
+
4392
  // [range.take.sentinel], class template take_view::sentinel
4393
+ template<bool> class sentinel; // exposition only
4394
+
4395
  public:
4396
+ take_view() requires default_initializable<V> = default;
4397
+ constexpr explicit take_view(V base, range_difference_t<V> count);
4398
 
4399
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4400
  constexpr V base() && { return std::move(base_); }
4401
 
4402
  constexpr auto begin() requires (!simple-view<V>) {
4403
  if constexpr (sized_range<V>) {
4404
+ if constexpr (random_access_range<V>) {
4405
  return ranges::begin(base_);
4406
+ } else {
4407
+ auto sz = range_difference_t<V>(size());
4408
+ return counted_iterator(ranges::begin(base_), sz);
4409
+ }
4410
+ } else if constexpr (sized_sentinel_for<sentinel_t<V>, iterator_t<V>>) {
4411
+ auto it = ranges::begin(base_);
4412
+ auto sz = std::min(count_, ranges::end(base_) - it);
4413
+ return counted_iterator(std::move(it), sz);
4414
+ } else {
4415
+ return counted_iterator(ranges::begin(base_), count_);
4416
  }
 
 
4417
  }
4418
 
4419
  constexpr auto begin() const requires range<const V> {
4420
  if constexpr (sized_range<const V>) {
4421
+ if constexpr (random_access_range<const V>) {
4422
  return ranges::begin(base_);
4423
+ } else {
4424
+ auto sz = range_difference_t<const V>(size());
4425
+ return counted_iterator(ranges::begin(base_), sz);
4426
+ }
4427
+ } else if constexpr (sized_sentinel_for<sentinel_t<const V>, iterator_t<const V>>) {
4428
+ auto it = ranges::begin(base_);
4429
+ auto sz = std::min(count_, ranges::end(base_) - it);
4430
+ return counted_iterator(std::move(it), sz);
4431
+ } else {
4432
+ return counted_iterator(ranges::begin(base_), count_);
4433
  }
 
 
4434
  }
4435
 
4436
  constexpr auto end() requires (!simple-view<V>) {
4437
  if constexpr (sized_range<V>) {
4438
  if constexpr (random_access_range<V>)
4439
+ return ranges::begin(base_) + range_difference_t<V>(size());
4440
  else
4441
  return default_sentinel;
4442
+ } else if constexpr (sized_sentinel_for<sentinel_t<V>, iterator_t<V>>) {
4443
+ return default_sentinel;
4444
+ } else {
4445
  return sentinel<false>{ranges::end(base_)};
4446
  }
4447
+ }
4448
 
4449
  constexpr auto end() const requires range<const V> {
4450
  if constexpr (sized_range<const V>) {
4451
  if constexpr (random_access_range<const V>)
4452
+ return ranges::begin(base_) + range_difference_t<const V>(size());
4453
  else
4454
  return default_sentinel;
4455
+ } else if constexpr (sized_sentinel_for<sentinel_t<const V>, iterator_t<const V>>) {
4456
+ return default_sentinel;
4457
+ } else {
4458
  return sentinel<true>{ranges::end(base_)};
4459
  }
4460
+ }
4461
 
4462
  constexpr auto size() requires sized_range<V> {
4463
  auto n = ranges::size(base_);
4464
  return ranges::min(n, static_cast<decltype(n)>(count_));
4465
  }
 
4468
  auto n = ranges::size(base_);
4469
  return ranges::min(n, static_cast<decltype(n)>(count_));
4470
  }
4471
  };
4472
 
4473
+ template<class R>
4474
  take_view(R&&, range_difference_t<R>)
4475
  -> take_view<views::all_t<R>>;
4476
  }
4477
  ```
4478
 
4479
  ``` cpp
4480
+ constexpr explicit take_view(V base, range_difference_t<V> count);
4481
  ```
4482
 
4483
+ *Preconditions:* `count >= 0` is `true`.
4484
+
4485
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
4486
  with `count`.
4487
 
4488
  #### Class template `take_view::sentinel` <a id="range.take.sentinel">[[range.take.sentinel]]</a>
4489
 
 
4491
  namespace std::ranges {
4492
  template<view V>
4493
  template<bool Const>
4494
  class take_view<V>::sentinel {
4495
  private:
4496
+ using Base = maybe-const<Const, V>; // exposition only
4497
+ template<bool OtherConst>
4498
+ using CI = counted_iterator<iterator_t<maybe-const<OtherConst, V>>>; // exposition only
4499
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
4500
+
4501
  public:
4502
  sentinel() = default;
4503
  constexpr explicit sentinel(sentinel_t<Base> end);
4504
  constexpr sentinel(sentinel<!Const> s)
4505
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4506
 
4507
  constexpr sentinel_t<Base> base() const;
4508
 
4509
+ friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
4510
+
4511
+ template<bool OtherConst = !Const>
4512
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4513
+ friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
4514
  };
4515
  }
4516
  ```
4517
 
4518
  ``` cpp
 
4533
  ```
4534
 
4535
  *Effects:* Equivalent to: `return `*`end_`*`;`
4536
 
4537
  ``` cpp
4538
+ friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
4539
+
4540
+ template<bool OtherConst = !Const>
4541
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4542
+ friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);
4543
  ```
4544
 
4545
  *Effects:* Equivalent to:
4546
  `return y.count() == 0 || y.base() == x.`*`end_`*`;`
4547
 
4548
  ### Take while view <a id="range.take.while">[[range.take.while]]</a>
4549
 
4550
  #### Overview <a id="range.take.while.overview">[[range.take.while.overview]]</a>
4551
 
4552
+ Given a unary predicate `pred` and a view `r`, `take_while_view`
4553
+ produces a view of the range \[`ranges::begin(r)`,
4554
  `ranges::find_if_not(r, pred)`).
4555
 
4556
  The name `views::take_while` denotes a range adaptor object
4557
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
4558
  expression `views::take_while(E, F)` is expression-equivalent to
4559
+ `take_while_view(E, F)`.
4560
 
4561
  [*Example 1*:
4562
 
4563
  ``` cpp
4564
  auto input = istringstream{"0 1 2 3 4 5 6 7 8 9"};
4565
  auto small = [](const auto x) noexcept { return x < 5; };
4566
+ auto small_ints = views::istream<int>(input) | views::take_while(small);
4567
  for (const auto i : small_ints) {
4568
  cout << i << ' '; // prints 0 1 2 3 4
4569
  }
4570
  auto i = 0;
4571
  input >> i;
 
4584
  class take_while_view : public view_interface<take_while_view<V, Pred>> {
4585
  // [range.take.while.sentinel], class template take_while_view::sentinel
4586
  template<bool> class sentinel; // exposition only
4587
 
4588
  V base_ = V(); // exposition only
4589
+ movable-box<Pred> pred_; // exposition only
4590
 
4591
  public:
4592
+ take_while_view() requires default_initializable<V> && default_initializable<Pred> = default;
4593
+ constexpr explicit take_while_view(V base, Pred pred);
4594
 
4595
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4596
  constexpr V base() && { return std::move(base_); }
4597
 
4598
  constexpr const Pred& pred() const;
4599
 
4600
  constexpr auto begin() requires (!simple-view<V>)
4601
  { return ranges::begin(base_); }
4602
 
4603
+ constexpr auto begin() const
4604
+ requires range<const V> &&
4605
+ indirect_unary_predicate<const Pred, iterator_t<const V>>
4606
  { return ranges::begin(base_); }
4607
 
4608
  constexpr auto end() requires (!simple-view<V>)
4609
  { return sentinel<false>(ranges::end(base_), addressof(*pred_)); }
4610
 
4611
+ constexpr auto end() const
4612
+ requires range<const V> &&
4613
+ indirect_unary_predicate<const Pred, iterator_t<const V>>
4614
  { return sentinel<true>(ranges::end(base_), addressof(*pred_)); }
4615
  };
4616
 
4617
  template<class R, class Pred>
4618
  take_while_view(R&&, Pred) -> take_while_view<views::all_t<R>, Pred>;
4619
  }
4620
  ```
4621
 
4622
  ``` cpp
4623
+ constexpr explicit take_while_view(V base, Pred pred);
4624
  ```
4625
 
4626
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
4627
  `std::move(pred)`.
4628
 
 
4638
  namespace std::ranges {
4639
  template<view V, class Pred>
4640
  requires input_range<V> && is_object_v<Pred> &&
4641
  indirect_unary_predicate<const Pred, iterator_t<V>>
4642
  template<bool Const>
4643
+ class take_while_view<V, Pred>::sentinel {
4644
+ using Base = maybe-const<Const, V>; // exposition only
4645
 
4646
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
4647
  const Pred* pred_ = nullptr; // exposition only
4648
+
4649
  public:
4650
  sentinel() = default;
4651
  constexpr explicit sentinel(sentinel_t<Base> end, const Pred* pred);
4652
  constexpr sentinel(sentinel<!Const> s)
4653
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4654
 
4655
  constexpr sentinel_t<Base> base() const { return end_; }
4656
 
4657
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
4658
+
4659
+ template<bool OtherConst = !Const>
4660
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4661
+ friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x,
4662
+ const sentinel& y);
4663
  };
4664
  }
4665
  ```
4666
 
4667
  ``` cpp
 
4673
  ``` cpp
4674
  constexpr sentinel(sentinel<!Const> s)
4675
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
4676
  ```
4677
 
4678
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)` and
4679
+ *pred\_* with `s.`*`pred_`*.
4680
 
4681
  ``` cpp
4682
  friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);
4683
+
4684
+ template<bool OtherConst = !Const>
4685
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
4686
+ friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x,
4687
+ const sentinel& y);
4688
  ```
4689
 
4690
  *Effects:* Equivalent to:
4691
  `return y.`*`end_`*` == x || !invoke(*y.`*`pred_`*`, *x);`
4692
 
4693
  ### Drop view <a id="range.drop">[[range.drop]]</a>
4694
 
4695
  #### Overview <a id="range.drop.overview">[[range.drop.overview]]</a>
4696
 
4697
+ `drop_view` produces a view excluding the first N elements from another
4698
+ view, or an empty range if the adapted view contains fewer than N
4699
+ elements.
4700
 
4701
  The name `views::drop` denotes a range adaptor object
4702
  [[range.adaptor.object]]. Let `E` and `F` be expressions, let `T` be
4703
  `remove_cvref_t<decltype((E))>`, and let `D` be
4704
  `range_difference_t<decltype((E))>`. If `decltype((F))` does not model
4705
  `convertible_to<D>`, `views::drop(E, F)` is ill-formed. Otherwise, the
4706
  expression `views::drop(E, F)` is expression-equivalent to:
4707
 
4708
+ - If `T` is a specialization of `empty_view` [[range.empty.view]], then
4709
+ `((void)F, decay-copy(E))`, except that the evaluations of `E` and `F`
4710
+ are indeterminately sequenced.
4711
  - Otherwise, if `T` models `random_access_range` and `sized_range` and
4712
  is
4713
+ - a specialization of `span` [[views.span]],
 
4714
  - a specialization of `basic_string_view` [[string.view]],
4715
+ - a specialization of `iota_view` [[range.iota.view]], or
4716
+ - a specialization of `subrange` [[range.subrange]] where
4717
+ `T::StoreSize` is `false`,
4718
 
4719
  then
4720
+ `U(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::end(E))`,
4721
+ except that `E` is evaluated only once, where `U` is
4722
+ `span<typename T::element_type>` if `T` is a specialization of `span`
4723
+ and `T` otherwise.
4724
+ - Otherwise, if `T` is a specialization of `subrange` [[range.subrange]]
4725
+ that models `random_access_range` and `sized_range`, then
4726
+ `T(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::{}end(E),
4727
+ to-unsigned-like(ranges::distance(E) -
4728
+ std::min<D>(ranges::distance(E), F)))`, except that `E` and `F` are
4729
+ each evaluated only once.
4730
+ - Otherwise, if `T` is a specialization of `repeat_view`
4731
+ [[range.repeat.view]]:
4732
+ - if `T` models `sized_range`, then
4733
+ ``` cpp
4734
+ views::repeat(*E.value_, ranges::distance(E) - std::min<D>(ranges::distance(E), F))
4735
+ ```
4736
+
4737
+ except that `E` is evaluated only once;
4738
+ - otherwise, `((void)F, decay-copy(E))`, except that the evaluations
4739
+ of `E` and `F` are indeterminately sequenced.
4740
+ - Otherwise, `drop_view(E, F)`.
4741
 
4742
  [*Example 1*:
4743
 
4744
  ``` cpp
4745
  auto ints = views::iota(0) | views::take(10);
4746
+ for (auto i : ints | views::drop(5)) {
 
4747
  cout << i << ' '; // prints 5 6 7 8 9
4748
  }
4749
  ```
4750
 
4751
  — *end example*]
 
4755
  ``` cpp
4756
  namespace std::ranges {
4757
  template<view V>
4758
  class drop_view : public view_interface<drop_view<V>> {
4759
  public:
4760
+ drop_view() requires default_initializable<V> = default;
4761
+ constexpr explicit drop_view(V base, range_difference_t<V> count);
4762
 
4763
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4764
  constexpr V base() && { return std::move(base_); }
4765
 
4766
  constexpr auto begin()
4767
+ requires (!(simple-view<V> &&
4768
+ random_access_range<const V> && sized_range<const V>));
4769
  constexpr auto begin() const
4770
+ requires random_access_range<const V> && sized_range<const V>;
4771
 
4772
+ constexpr auto end() requires (!simple-view<V>)
 
4773
  { return ranges::end(base_); }
4774
 
4775
+ constexpr auto end() const requires range<const V>
 
4776
  { return ranges::end(base_); }
4777
 
4778
+ constexpr auto size() requires sized_range<V> {
 
 
4779
  const auto s = ranges::size(base_);
4780
  const auto c = static_cast<decltype(s)>(count_);
4781
  return s < c ? 0 : s - c;
4782
  }
4783
 
4784
+ constexpr auto size() const requires sized_range<const V> {
 
 
4785
  const auto s = ranges::size(base_);
4786
  const auto c = static_cast<decltype(s)>(count_);
4787
  return s < c ? 0 : s - c;
4788
  }
4789
+
4790
  private:
4791
  V base_ = V(); // exposition only
4792
  range_difference_t<V> count_ = 0; // exposition only
4793
  };
4794
 
 
4796
  drop_view(R&&, range_difference_t<R>) -> drop_view<views::all_t<R>>;
4797
  }
4798
  ```
4799
 
4800
  ``` cpp
4801
+ constexpr explicit drop_view(V base, range_difference_t<V> count);
4802
  ```
4803
 
4804
  *Preconditions:* `count >= 0` is `true`.
4805
 
4806
  *Effects:* Initializes *base\_* with `std::move(base)` and *count\_*
4807
  with `count`.
4808
 
4809
  ``` cpp
4810
  constexpr auto begin()
4811
+ requires (!(simple-view<V> &&
4812
+ random_access_range<const V> && sized_range<const V>));
4813
  constexpr auto begin() const
4814
+ requires random_access_range<const V> && sized_range<const V>;
4815
  ```
4816
 
4817
  *Returns:*
4818
+ `ranges::next(ranges::begin(`*`base_`*`), `*`count_`*`, ranges::end(`*`base_`*`))`.
4819
 
4820
  *Remarks:* In order to provide the amortized constant-time complexity
4821
  required by the `range` concept when `drop_view` models `forward_range`,
4822
  the first overload caches the result within the `drop_view` for use on
4823
  subsequent calls.
 
4827
 
4828
  ### Drop while view <a id="range.drop.while">[[range.drop.while]]</a>
4829
 
4830
  #### Overview <a id="range.drop.while.overview">[[range.drop.while.overview]]</a>
4831
 
4832
+ Given a unary predicate `pred` and a view `r`, `drop_while_view`
4833
+ produces a view of the range \[`ranges::find_if_not(r, pred)`,
4834
  `ranges::end(r)`).
4835
 
4836
  The name `views::drop_while` denotes a range adaptor object
4837
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
4838
  expression `views::drop_while(E, F)` is expression-equivalent to
4839
+ `drop_while_view(E, F)`.
4840
 
4841
  [*Example 1*:
4842
 
4843
  ``` cpp
4844
+ constexpr auto source = " \t \t \t hello there"sv;
4845
  auto is_invisible = [](const auto x) { return x == ' ' || x == '\t'; };
4846
+ auto skip_ws = views::drop_while(source, is_invisible);
4847
  for (auto c : skip_ws) {
4848
  cout << c; // prints hello there with no leading space
4849
  }
4850
  ```
4851
 
 
4858
  template<view V, class Pred>
4859
  requires input_range<V> && is_object_v<Pred> &&
4860
  indirect_unary_predicate<const Pred, iterator_t<V>>
4861
  class drop_while_view : public view_interface<drop_while_view<V, Pred>> {
4862
  public:
4863
+ drop_while_view() requires default_initializable<V> && default_initializable<Pred> = default;
4864
+ constexpr explicit drop_while_view(V base, Pred pred);
4865
 
4866
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4867
  constexpr V base() && { return std::move(base_); }
4868
 
4869
  constexpr const Pred& pred() const;
4870
 
4871
  constexpr auto begin();
4872
 
4873
+ constexpr auto end() { return ranges::end(base_); }
 
4874
 
4875
  private:
4876
  V base_ = V(); // exposition only
4877
+ movable-box<Pred> pred_; // exposition only
4878
  };
4879
 
4880
  template<class R, class Pred>
4881
  drop_while_view(R&&, Pred) -> drop_while_view<views::all_t<R>, Pred>;
4882
  }
4883
  ```
4884
 
4885
  ``` cpp
4886
+ constexpr explicit drop_while_view(V base, Pred pred);
4887
  ```
4888
 
4889
  *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
4890
  `std::move(pred)`.
4891
 
 
4897
 
4898
  ``` cpp
4899
  constexpr auto begin();
4900
  ```
4901
 
4902
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
4903
+
4904
+ *Returns:* `ranges::find_if_not(`*`base_`*`, cref(*`*`pred_`*`))`.
4905
 
4906
  *Remarks:* In order to provide the amortized constant-time complexity
4907
  required by the `range` concept when `drop_while_view` models
4908
  `forward_range`, the first call caches the result within the
4909
  `drop_while_view` for use on subsequent calls.
 
4914
 
4915
  ### Join view <a id="range.join">[[range.join]]</a>
4916
 
4917
  #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
4918
 
4919
+ `join_view` flattens a view of ranges into a view.
4920
 
4921
  The name `views::join` denotes a range adaptor object
4922
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
4923
+ `views::join(E)` is expression-equivalent to
4924
+ `join_view<views::all_t<decltype((E))>>{E}`.
4925
 
4926
  [*Example 1*:
4927
 
4928
  ``` cpp
4929
  vector<string> ss{"hello", " ", "world", "!"};
4930
+ for (char ch : ss | views::join)
4931
+ cout << ch; // prints hello world!
 
4932
  ```
4933
 
4934
  — *end example*]
4935
 
4936
  #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
4937
 
4938
  ``` cpp
4939
  namespace std::ranges {
4940
  template<input_range V>
4941
+ requires view<V> && input_range<range_reference_t<V>>
 
 
4942
  class join_view : public view_interface<join_view<V>> {
4943
  private:
4944
+ using InnerRng = range_reference_t<V>; // exposition only
4945
+
4946
  // [range.join.iterator], class template join_view::iterator
4947
  template<bool Const>
4948
  struct iterator; // exposition only
4949
+
4950
  // [range.join.sentinel], class template join_view::sentinel
4951
  template<bool Const>
4952
  struct sentinel; // exposition only
4953
 
4954
  V base_ = V(); // exposition only
4955
+
4956
+ non-propagating-cache<iterator_t<V>> outer_; // exposition only, present only
4957
+ // when !forward_range<V>
4958
+ non-propagating-cache<remove_cv_t<InnerRng>> inner_; // exposition only, present only
4959
+ // if is_reference_v<InnerRng> is false
4960
+
4961
  public:
4962
+ join_view() requires default_initializable<V> = default;
4963
  constexpr explicit join_view(V base);
4964
 
4965
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4966
  constexpr V base() && { return std::move(base_); }
4967
 
4968
  constexpr auto begin() {
4969
+ if constexpr (forward_range<V>) {
4970
  constexpr bool use_const = simple-view<V> &&
4971
+ is_reference_v<InnerRng>;
4972
  return iterator<use_const>{*this, ranges::begin(base_)};
4973
+ } else {
4974
+ outer_ = ranges::begin(base_);
4975
+ return iterator<false>{*this};
4976
+ }
4977
  }
4978
 
4979
  constexpr auto begin() const
4980
+ requires forward_range<const V> &&
4981
+ is_reference_v<range_reference_t<const V>> &&
4982
+ input_range<range_reference_t<const V>>
4983
+ { return iterator<true>{*this, ranges::begin(base_)}; }
4984
 
4985
  constexpr auto end() {
4986
  if constexpr (forward_range<V> &&
4987
  is_reference_v<InnerRng> && forward_range<InnerRng> &&
4988
  common_range<V> && common_range<InnerRng>)
 
4990
  else
4991
  return sentinel<simple-view<V>>{*this};
4992
  }
4993
 
4994
  constexpr auto end() const
4995
+ requires forward_range<const V> &&
 
 
4996
  is_reference_v<range_reference_t<const V>> &&
4997
+ input_range<range_reference_t<const V>> {
4998
+ if constexpr (forward_range<range_reference_t<const V>> &&
4999
  common_range<const V> &&
5000
  common_range<range_reference_t<const V>>)
5001
  return iterator<true>{*this, ranges::end(base_)};
5002
  else
5003
  return sentinel<true>{*this};
 
5018
  #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
5019
 
5020
  ``` cpp
5021
  namespace std::ranges {
5022
  template<input_range V>
5023
+ requires view<V> && input_range<range_reference_t<V>>
 
 
5024
  template<bool Const>
5025
  struct join_view<V>::iterator {
5026
  private:
5027
+ using Parent = maybe-const<Const, join_view>; // exposition only
5028
+ using Base = maybe-const<Const, V>; // exposition only
5029
+ using OuterIter = iterator_t<Base>; // exposition only
5030
+ using InnerIter = iterator_t<range_reference_t<Base>>; // exposition only
5031
 
5032
  static constexpr bool ref-is-glvalue = // exposition only
5033
  is_reference_v<range_reference_t<Base>>;
5034
 
5035
+ OuterIter outer_ = OuterIter(); // exposition only, present only
5036
+ // if Base models forward_range
5037
+ optional<InnerIter> inner_; // exposition only
5038
  Parent* parent_ = nullptr; // exposition only
5039
 
5040
  constexpr void satisfy(); // exposition only
5041
+
5042
+ constexpr OuterIter& outer(); // exposition only
5043
+ constexpr const OuterIter& outer() const; // exposition only
5044
+
5045
+ constexpr iterator(Parent& parent, OuterIter outer)
5046
+ requires forward_range<Base>; // exposition only
5047
+ constexpr explicit iterator(Parent& parent)
5048
+ requires (!forward_range<Base>); // exposition only
5049
+
5050
  public:
5051
  using iterator_concept = see below;
5052
+ using iterator_category = see below; // not always present
5053
  using value_type = range_value_t<range_reference_t<Base>>;
5054
  using difference_type = see below;
5055
 
5056
  iterator() = default;
 
5057
  constexpr iterator(iterator<!Const> i)
5058
  requires Const &&
5059
+ convertible_to<iterator_t<V>, OuterIter> &&
5060
+ convertible_to<iterator_t<InnerRng>, InnerIter>;
 
5061
 
5062
+ constexpr decltype(auto) operator*() const { return **inner_; }
5063
 
5064
+ constexpr InnerIter operator->() const
5065
+ requires has-arrow<InnerIter> && copyable<InnerIter>;
5066
 
5067
  constexpr iterator& operator++();
5068
  constexpr void operator++(int);
5069
  constexpr iterator operator++(int)
5070
  requires ref-is-glvalue && forward_range<Base> &&
 
5079
  requires ref-is-glvalue && bidirectional_range<Base> &&
5080
  bidirectional_range<range_reference_t<Base>> &&
5081
  common_range<range_reference_t<Base>>;
5082
 
5083
  friend constexpr bool operator==(const iterator& x, const iterator& y)
5084
+ requires ref-is-glvalue && forward_range<Base> &&
5085
  equality_comparable<iterator_t<range_reference_t<Base>>>;
5086
 
5087
  friend constexpr decltype(auto) iter_move(const iterator& i)
5088
+ noexcept(noexcept(ranges::iter_move(*i.inner_))) {
5089
+ return ranges::iter_move(*i.inner_);
5090
  }
5091
 
5092
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
5093
+ noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
5094
+ requires indirectly_swappable<InnerIter>;
5095
  };
5096
  }
5097
  ```
5098
 
5099
  `iterator::iterator_concept` is defined as follows:
5100
 
5101
+ - If *`ref-is-glvalue`* is `true`, *`Base`* models
5102
+ `bidirectional_range`, and `range_reference_t<Base>` models both
5103
+ `bidirectional_range` and `common_range`, then `iterator_concept`
5104
+ denotes `bidirectional_iterator_tag`.
5105
  - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
5106
  `range_reference_t<Base>` each model , then `iterator_concept` denotes
5107
  `forward_iterator_tag`.
5108
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
5109
 
5110
+ The member *typedef-name* `iterator_category` is defined if and only if
5111
+ *`ref-is-glvalue`* is `true`, *`Base`* models `forward_range`, and
5112
+ `range_reference_t<Base>` models `forward_range`. In that case,
5113
  `iterator::iterator_category` is defined as follows:
5114
 
5115
  - Let *OUTERC* denote
5116
  `iterator_traits<iterator_t<Base>>::iterator_category`, and let
5117
  *INNERC* denote
5118
  `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
5119
+ - If *OUTERC* and *INNERC* each model
5120
+ `derived_from<bidirectional_iterator_tag>` and
5121
+ `range_reference_t<Base>` models `common_range`, `iterator_category`
5122
  denotes `bidirectional_iterator_tag`.
 
 
 
5123
  - Otherwise, if *OUTERC* and *INNERC* each model
5124
+ `derived_from<forward_iterator_tag>`, `iterator_category` denotes
5125
+ `forward_iterator_tag`.
5126
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
5127
 
5128
  `iterator::difference_type` denotes the type:
5129
 
5130
  ``` cpp
5131
  common_type_t<
 
5135
 
5136
  `join_view` iterators use the *`satisfy`* function to skip over empty
5137
  inner ranges.
5138
 
5139
  ``` cpp
5140
+ constexpr OuterIter& outer();
5141
+ constexpr const OuterIter& outer() const;
5142
+ ```
5143
+
5144
+ *Returns:* *outer\_* if *Base* models `forward_range`; otherwise,
5145
+ `*`*`parent_`*`->`*`outer_`*.
5146
+
5147
+ ``` cpp
5148
+ constexpr void satisfy();
5149
  ```
5150
 
5151
  *Effects:* Equivalent to:
5152
 
5153
  ``` cpp
5154
+ auto update_inner = [this](const iterator_t<Base>& x) -> auto&& {
5155
+ if constexpr (ref-is-glvalue) // *x is a reference
5156
+ return *x;
5157
  else
5158
+ return parent_->inner_.emplace-deref(x);
5159
  };
5160
 
5161
+ for (; outer() != ranges::end(parent_->base_); ++outer()) {
5162
+ auto&& inner = update_inner(outer());
5163
  inner_ = ranges::begin(inner);
5164
+ if (*inner_ != ranges::end(inner))
5165
  return;
5166
  }
5167
  if constexpr (ref-is-glvalue)
5168
+ inner_.reset();
5169
  ```
5170
 
5171
  ``` cpp
5172
+ constexpr iterator(Parent& parent, OuterIter outer)
5173
+ requires forward_range<Base>;
5174
  ```
5175
 
5176
  *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
5177
  with `addressof(parent)`; then calls *`satisfy`*`()`.
5178
 
5179
+ ``` cpp
5180
+ constexpr explicit iterator(Parent& parent)
5181
+ requires (!forward_range<Base>);
5182
+ ```
5183
+
5184
+ *Effects:* Initializes *parent\_* with `addressof(parent)`; then calls
5185
+ *`satisfy`*`()`.
5186
+
5187
  ``` cpp
5188
  constexpr iterator(iterator<!Const> i)
5189
  requires Const &&
5190
+ convertible_to<iterator_t<V>, OuterIter> &&
5191
+ convertible_to<iterator_t<InnerRng>, InnerIter>;
 
5192
  ```
5193
 
5194
  *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
5195
  *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
5196
  `i.`*`parent_`*.
5197
 
5198
+ [*Note 1*: `Const` can only be `true` when *Base* models
5199
+ `forward_range`. — *end note*]
5200
+
5201
  ``` cpp
5202
+ constexpr InnerIter operator->() const
5203
+ requires has-arrow<InnerIter> && copyable<InnerIter>;
5204
  ```
5205
 
5206
+ *Effects:* Equivalent to: `return *`*`inner_`*`;`
5207
 
5208
  ``` cpp
5209
  constexpr iterator& operator++();
5210
  ```
5211
 
5212
  Let *`inner-range`* be:
5213
 
5214
+ - If *ref-is-glvalue* is `true`, `*`*`outer`*`()`.
5215
+ - Otherwise, `*`*`parent_`*`->`*`inner_`*.
5216
 
5217
  *Effects:* Equivalent to:
5218
 
5219
  ``` cpp
5220
+ if (++*inner_ == ranges::end(as-lvalue(inner-range))) {
5221
+ ++outer();
 
5222
  satisfy();
5223
  }
5224
  return *this;
5225
  ```
5226
 
 
5253
 
5254
  *Effects:* Equivalent to:
5255
 
5256
  ``` cpp
5257
  if (outer_ == ranges::end(parent_->base_))
5258
+ inner_ = ranges::end(as-lvalue(*--outer_));
5259
+ while (*inner_ == ranges::begin(as-lvalue(*outer_)))
5260
+ *inner_ = ranges::end(as-lvalue(*--outer_));
5261
+ --*inner_;
5262
  return *this;
5263
  ```
5264
 
5265
  ``` cpp
5266
  constexpr iterator operator--(int)
 
5277
  return tmp;
5278
  ```
5279
 
5280
  ``` cpp
5281
  friend constexpr bool operator==(const iterator& x, const iterator& y)
5282
+ requires ref-is-glvalue && forward_range<Base> &&
5283
  equality_comparable<iterator_t<range_reference_t<Base>>>;
5284
  ```
5285
 
5286
  *Effects:* Equivalent to:
5287
  `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
5288
 
5289
  ``` cpp
5290
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
5291
+ noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
5292
+ requires indirectly_swappable<InnerIter>;
5293
  ```
5294
 
5295
  *Effects:* Equivalent to:
5296
+ `return ranges::iter_swap(*x.`*`inner_`*`, *y.`*`inner_`*`);`
5297
 
5298
  #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
5299
 
5300
  ``` cpp
5301
  namespace std::ranges {
5302
  template<input_range V>
5303
+ requires view<V> && input_range<range_reference_t<V>>
 
 
5304
  template<bool Const>
5305
  struct join_view<V>::sentinel {
5306
  private:
5307
+ using Parent = maybe-const<Const, join_view>; // exposition only
5308
+ using Base = maybe-const<Const, V>; // exposition only
 
5309
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
5310
+
5311
  public:
5312
  sentinel() = default;
5313
 
5314
  constexpr explicit sentinel(Parent& parent);
5315
  constexpr sentinel(sentinel<!Const> s)
5316
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
5317
 
5318
+ template<bool OtherConst>
5319
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
5320
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5321
+ };
5322
+ }
5323
+ ```
5324
+
5325
+ ``` cpp
5326
+ constexpr explicit sentinel(Parent& parent);
5327
+ ```
5328
+
5329
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
5330
+
5331
+ ``` cpp
5332
+ constexpr sentinel(sentinel<!Const> s)
5333
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
5334
+ ```
5335
+
5336
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
5337
+
5338
+ ``` cpp
5339
+ template<bool OtherConst>
5340
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
5341
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5342
+ ```
5343
+
5344
+ *Effects:* Equivalent to: `return x.`*`outer`*`() == y.`*`end_`*`;`
5345
+
5346
+ ### Join with view <a id="range.join.with">[[range.join.with]]</a>
5347
+
5348
+ #### Overview <a id="range.join.with.overview">[[range.join.with.overview]]</a>
5349
+
5350
+ `join_with_view` takes a view and a delimiter, and flattens the view,
5351
+ inserting every element of the delimiter in between elements of the
5352
+ view. The delimiter can be a single element or a view of elements.
5353
+
5354
+ The name `views::join_with` denotes a range adaptor object
5355
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
5356
+ expression `views::join_with(E, F)` is expression-equivalent to
5357
+ `join_with_view(E, F)`.
5358
+
5359
+ [*Example 1*:
5360
+
5361
+ ``` cpp
5362
+ vector<string> vs = {"the", "quick", "brown", "fox"};
5363
+ for (char c : vs | views::join_with('-')) {
5364
+ cout << c;
5365
+ }
5366
+ // The above prints the-quick-brown-fox
5367
+ ```
5368
+
5369
+ — *end example*]
5370
+
5371
+ #### Class template `join_with_view` <a id="range.join.with.view">[[range.join.with.view]]</a>
5372
+
5373
+ ``` cpp
5374
+ namespace std::ranges {
5375
+ template<class R, class P>
5376
+ concept compatible-joinable-ranges = // exposition only
5377
+ common_with<range_value_t<R>, range_value_t<P>> &&
5378
+ common_reference_with<range_reference_t<R>, range_reference_t<P>> &&
5379
+ common_reference_with<range_rvalue_reference_t<R>, range_rvalue_reference_t<P>>;
5380
+
5381
+ template<class R>
5382
+ concept bidirectional-common = bidirectional_range<R> && common_range<R>; // exposition only
5383
+
5384
+ template<input_range V, forward_range Pattern>
5385
+ requires view<V> && input_range<range_reference_t<V>>
5386
+ && view<Pattern>
5387
+ && compatible-joinable-ranges<range_reference_t<V>, Pattern>
5388
+ class join_with_view : public view_interface<join_with_view<V, Pattern>> {
5389
+ using InnerRng = range_reference_t<V>; // exposition only
5390
+
5391
+ V base_ = V(); // exposition only
5392
+ non-propagating-cache<iterator_t<V>> outer_it_; // exposition only, present only
5393
+ // when !forward_range<V>
5394
+ non-propagating-cache<remove_cv_t<InnerRng>> inner_; // exposition only, present only
5395
+ // if is_reference_v<InnerRng> is false
5396
+ Pattern pattern_ = Pattern(); // exposition only
5397
+
5398
+ // [range.join.with.iterator], class template join_with_view::iterator
5399
+ template<bool Const> struct iterator; // exposition only
5400
+
5401
+ // [range.join.with.sentinel], class template join_with_view::sentinel
5402
+ template<bool Const> struct sentinel; // exposition only
5403
+
5404
+ public:
5405
+ join_with_view()
5406
+ requires default_initializable<V> && default_initializable<Pattern> = default;
5407
+
5408
+ constexpr explicit join_with_view(V base, Pattern pattern);
5409
+
5410
+ template<input_range R>
5411
+ requires constructible_from<V, views::all_t<R>> &&
5412
+ constructible_from<Pattern, single_view<range_value_t<InnerRng>>>
5413
+ constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);
5414
+
5415
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
5416
+ constexpr V base() && { return std::move(base_); }
5417
+
5418
+ constexpr auto begin() {
5419
+ if constexpr (forward_range<V>) {
5420
+ constexpr bool use_const =
5421
+ simple-view<V> && is_reference_v<InnerRng> && simple-view<Pattern>;
5422
+ return iterator<use_const>{*this, ranges::begin(base_)};
5423
+ }
5424
+ else {
5425
+ outer_it_ = ranges::begin(base_);
5426
+ return iterator<false>{*this};
5427
+ }
5428
+ }
5429
+ constexpr auto begin() const
5430
+ requires forward_range<const V> &&
5431
+ forward_range<const Pattern> &&
5432
+ is_reference_v<range_reference_t<const V>> &&
5433
+ input_range<range_reference_t<const V>> {
5434
+ return iterator<true>{*this, ranges::begin(base_)};
5435
+ }
5436
+
5437
+ constexpr auto end() {
5438
+ if constexpr (forward_range<V> &&
5439
+ is_reference_v<InnerRng> && forward_range<InnerRng> &&
5440
+ common_range<V> && common_range<InnerRng>)
5441
+ return iterator<simple-view<V> && simple-view<Pattern>>{*this, ranges::end(base_)};
5442
+ else
5443
+ return sentinel<simple-view<V> && simple-view<Pattern>>{*this};
5444
+ }
5445
+ constexpr auto end() const
5446
+ requires forward_range<const V> && forward_range<const Pattern> &&
5447
+ is_reference_v<range_reference_t<const V>> &&
5448
+ input_range<range_reference_t<const V>> {
5449
+ using InnerConstRng = range_reference_t<const V>;
5450
+ if constexpr (forward_range<InnerConstRng> &&
5451
+ common_range<const V> && common_range<InnerConstRng>)
5452
+ return iterator<true>{*this, ranges::end(base_)};
5453
+ else
5454
+ return sentinel<true>{*this};
5455
+ }
5456
+ };
5457
+
5458
+ template<class R, class P>
5459
+ join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>;
5460
+
5461
+ template<input_range R>
5462
+ join_with_view(R&&, range_value_t<range_reference_t<R>>)
5463
+ -> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>;
5464
+ }
5465
+ ```
5466
+
5467
+ ``` cpp
5468
+ constexpr explicit join_with_view(V base, Pattern pattern);
5469
+ ```
5470
+
5471
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pattern\_*
5472
+ with `std::move(pattern)`.
5473
+
5474
+ ``` cpp
5475
+ template<input_range R>
5476
+ requires constructible_from<V, views::all_t<R>> &&
5477
+ constructible_from<Pattern, single_view<range_value_t<InnerRng>>>
5478
+ constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);
5479
+ ```
5480
+
5481
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`
5482
+ and *pattern\_* with `views::single(std::move(e))`.
5483
+
5484
+ #### Class template `join_with_view::iterator` <a id="range.join.with.iterator">[[range.join.with.iterator]]</a>
5485
+
5486
+ ``` cpp
5487
+ namespace std::ranges {
5488
+ template<input_range V, forward_range Pattern>
5489
+ requires view<V> && input_range<range_reference_t<V>>
5490
+ && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
5491
+ template<bool Const>
5492
+ class join_with_view<V, Pattern>::iterator {
5493
+ using Parent = maybe-const<Const, join_with_view>; // exposition only
5494
+ using Base = maybe-const<Const, V>; // exposition only
5495
+ using InnerBase = range_reference_t<Base>; // exposition only
5496
+ using PatternBase = maybe-const<Const, Pattern>; // exposition only
5497
+
5498
+ using OuterIter = iterator_t<Base>; // exposition only
5499
+ using InnerIter = iterator_t<InnerBase>; // exposition only
5500
+ using PatternIter = iterator_t<PatternBase>; // exposition only
5501
+
5502
+ static constexpr bool ref-is-glvalue = is_reference_v<InnerBase>; // exposition only
5503
+
5504
+ Parent* parent_ = nullptr; // exposition only
5505
+ OuterIter outer_it_ = OuterIter(); // exposition only, present only
5506
+ // if Base models forward_range
5507
+ variant<PatternIter, InnerIter> inner_it_; // exposition only
5508
+
5509
+ constexpr iterator(Parent& parent, OuterIter outer)
5510
+ requires forward_range<Base>; // exposition only
5511
+ constexpr explicit iterator(Parent& parent)
5512
+ requires (!forward_range<Base>); // exposition only
5513
+ constexpr OuterIter& outer(); // exposition only
5514
+ constexpr const OuterIter& outer() const; // exposition only
5515
+ constexpr auto& update-inner(); // exposition only
5516
+ constexpr auto& get-inner(); // exposition only
5517
+ constexpr void satisfy(); // exposition only
5518
+
5519
+ public:
5520
+ using iterator_concept = see below;
5521
+ using iterator_category = see below; // not always present
5522
+ using value_type = see below;
5523
+ using difference_type = see below;
5524
+
5525
+ iterator() = default;
5526
+ constexpr iterator(iterator<!Const> i)
5527
+ requires Const && convertible_to<iterator_t<V>, OuterIter> &&
5528
+ convertible_to<iterator_t<InnerRng>, InnerIter> &&
5529
+ convertible_to<iterator_t<Pattern>, PatternIter>;
5530
+
5531
+ constexpr decltype(auto) operator*() const;
5532
+
5533
+ constexpr iterator& operator++();
5534
+ constexpr void operator++(int);
5535
+ constexpr iterator operator++(int)
5536
+ requires ref-is-glvalue && forward_iterator<OuterIter> &&
5537
+ forward_iterator<InnerIter>;
5538
+
5539
+ constexpr iterator& operator--()
5540
+ requires ref-is-glvalue && bidirectional_range<Base> &&
5541
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
5542
+ constexpr iterator operator--(int)
5543
+ requires ref-is-glvalue && bidirectional_range<Base> &&
5544
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
5545
+
5546
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
5547
+ requires ref-is-glvalue && forward_range<Base> &&
5548
+ equality_comparable<InnerIter>;
5549
+
5550
+ friend constexpr decltype(auto) iter_move(const iterator& x) {
5551
+ using rvalue_reference = common_reference_t<
5552
+ iter_rvalue_reference_t<InnerIter>,
5553
+ iter_rvalue_reference_t<PatternIter>>;
5554
+ return visit<rvalue_reference>(ranges::iter_move, x.inner_it_);
5555
+ }
5556
+
5557
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
5558
+ requires indirectly_swappable<InnerIter, PatternIter> {
5559
+ visit(ranges::iter_swap, x.inner_it_, y.inner_it_);
5560
+ }
5561
+ };
5562
+ }
5563
+ ```
5564
+
5565
+ `iterator::iterator_concept` is defined as follows:
5566
+
5567
+ - If *`ref-is-glvalue`* is `true`, *`Base`* models
5568
+ `bidirectional_range`, and *`InnerBase`* and *`PatternBase`* each
5569
+ model `bidirectional-common`, then `iterator_concept` denotes
5570
+ `bidirectional_iterator_tag`.
5571
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
5572
+ *`InnerBase`* each model `forward_range`, then `iterator_concept`
5573
+ denotes `forward_iterator_tag`.
5574
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
5575
+
5576
+ The member *typedef-name* `iterator_category` is defined if and only if
5577
+ *`ref-is-glvalue`* is `true`, and *`Base`* and *`InnerBase`* each model
5578
+ `forward_range`. In that case, `iterator::iterator_category` is defined
5579
+ as follows:
5580
+
5581
+ - Let *OUTERC* denote `iterator_traits<OuterIter>::iterator_category`,
5582
+ let *INNERC* denote `iterator_traits<InnerIter>::iterator_category`,
5583
+ and let *PATTERNC* denote
5584
+ `iterator_-traits<PatternIter>::iterator_category`.
5585
+ - If
5586
+ ``` cpp
5587
+ is_reference_v<common_reference_t<iter_reference_t<InnerIter>,
5588
+ iter_reference_t<PatternIter>>>
5589
+ ```
5590
+
5591
+ is `false`, `iterator_category` denotes `input_iterator_tag`.
5592
+ - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
5593
+ `derived_from<bidirectional_iterator_category>` and *`InnerBase`* and
5594
+ *`PatternBase`* each model `common_range`, `iterator_category` denotes
5595
+ `bidirectional_iterator_tag`.
5596
+ - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
5597
+ `derived_from<forward_iterator_tag>`, `iterator_category` denotes
5598
+ `forward_iterator_tag`.
5599
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
5600
+
5601
+ `iterator::value_type` denotes the type:
5602
+
5603
+ ``` cpp
5604
+ common_type_t<iter_value_t<InnerIter>, iter_value_t<PatternIter>>
5605
+ ```
5606
+
5607
+ `iterator::difference_type` denotes the type:
5608
+
5609
+ ``` cpp
5610
+ common_type_t<
5611
+ iter_difference_t<OuterIter>,
5612
+ iter_difference_t<InnerIter>,
5613
+ iter_difference_t<PatternIter>>
5614
+ ```
5615
+
5616
+ ``` cpp
5617
+ constexpr OuterIter& outer();
5618
+ constexpr const OuterIter& outer() const;
5619
+ ```
5620
+
5621
+ *Returns:* *outer_it\_* if *Base* models `forward_range`; otherwise,
5622
+ `*`*`parent_`*`->`*`outer_it_`*.
5623
+
5624
+ ``` cpp
5625
+ constexpr auto& update-inner();
5626
+ ```
5627
+
5628
+ *Effects:* Equivalent to:
5629
+
5630
+ ``` cpp
5631
+ if constexpr (ref-is-glvalue)
5632
+ return as-lvalue(*outer());
5633
+ else
5634
+ return parent_->inner_.emplace-deref(outer());
5635
+ ```
5636
+
5637
+ ``` cpp
5638
+ constexpr auto& get-inner();
5639
+ ```
5640
+
5641
+ *Effects:* Equivalent to:
5642
+
5643
+ ``` cpp
5644
+ if constexpr (ref-is-glvalue)
5645
+ return as-lvalue(*outer());
5646
+ else
5647
+ return *parent_->inner_;
5648
+ ```
5649
+
5650
+ ``` cpp
5651
+ constexpr void satisfy();
5652
+ ```
5653
+
5654
+ *Effects:* Equivalent to:
5655
+
5656
+ ``` cpp
5657
+ while (true) {
5658
+ if (inner_it_.index() == 0) {
5659
+ if (std::get<0>(inner_it_) != ranges::end(parent_->pattern_))
5660
+ break;
5661
+ inner_it_.emplace<1>(ranges::begin(update-inner()));
5662
+ } else {
5663
+ if (std::get<1>(inner_it_) != ranges::end(get-inner()))
5664
+ break;
5665
+ if (++outer() == ranges::end(parent_->base_)) {
5666
+ if constexpr (ref-is-glvalue)
5667
+ inner_it_.emplace<0>();
5668
+ break;
5669
+ }
5670
+ inner_it_.emplace<0>(ranges::begin(parent_->pattern_));
5671
+ }
5672
+ }
5673
+ ```
5674
+
5675
+ [*Note 1*: `join_with_view` iterators use the *satisfy* function to
5676
+ skip over empty inner ranges. — *end note*]
5677
+
5678
+ ``` cpp
5679
+ constexpr iterator(Parent& parent, OuterIter outer)
5680
+ requires forward_range<Base>;
5681
+ constexpr explicit iterator(Parent& parent)
5682
+ requires (!forward_range<Base>);
5683
+ ```
5684
+
5685
+ *Effects:* Initializes *parent\_* with `addressof(parent)`. For the
5686
+ first overload, also initializes *outer_it\_* with `std::move(outer)`.
5687
+ Then, equivalent to:
5688
+
5689
+ ``` cpp
5690
+ if (outer() != ranges::end(parent_->base_)) {
5691
+ inner_it_.emplace<1>(ranges::begin(update-inner()));
5692
+ satisfy();
5693
+ }
5694
+ ```
5695
+
5696
+ ``` cpp
5697
+ constexpr iterator(iterator<!Const> i)
5698
+ requires Const && convertible_to<iterator_t<V>, OuterIter> &&
5699
+ convertible_to<iterator_t<InnerRng>, InnerIter> &&
5700
+ convertible_to<iterator_t<Pattern>, PatternIter>;
5701
+ ```
5702
+
5703
+ *Effects:* Initializes *outer_it\_* with `std::move(i.`*`outer_it_`*`)`
5704
+ and *parent\_* with `i.`*`parent_`*. Then, equivalent to:
5705
+
5706
+ ``` cpp
5707
+ if (i.inner_it_.index() == 0)
5708
+ inner_it_.emplace<0>(std::get<0>(std::move(i.inner_it_)));
5709
+ else
5710
+ inner_it_.emplace<1>(std::get<1>(std::move(i.inner_it_)));
5711
+ ```
5712
+
5713
+ [*Note 2*: `Const` can only be `true` when *Base* models
5714
+ `forward_range`. — *end note*]
5715
+
5716
+ ``` cpp
5717
+ constexpr decltype(auto) operator*() const;
5718
+ ```
5719
+
5720
+ *Effects:* Equivalent to:
5721
+
5722
+ ``` cpp
5723
+ using reference =
5724
+ common_reference_t<iter_reference_t<InnerIter>, iter_reference_t<PatternIter>>;
5725
+ return visit([](auto& it) -> reference { return *it; }, inner_it_);
5726
+ ```
5727
+
5728
+ ``` cpp
5729
+ constexpr iterator& operator++();
5730
+ ```
5731
+
5732
+ *Effects:* Equivalent to:
5733
+
5734
+ ``` cpp
5735
+ visit([](auto& it){ ++it; }, inner_it_);
5736
+ satisfy();
5737
+ return *this;
5738
+ ```
5739
+
5740
+ ``` cpp
5741
+ constexpr void operator++(int);
5742
+ ```
5743
+
5744
+ *Effects:* Equivalent to `++*this`.
5745
+
5746
+ ``` cpp
5747
+ constexpr iterator operator++(int)
5748
+ requires ref-is-glvalue && forward_iterator<OuterIter> && forward_iterator<InnerIter>;
5749
+ ```
5750
+
5751
+ *Effects:* Equivalent to:
5752
+
5753
+ ``` cpp
5754
+ iterator tmp = *this;
5755
+ ++*this;
5756
+ return tmp;
5757
+ ```
5758
+
5759
+ ``` cpp
5760
+ constexpr iterator& operator--()
5761
+ requires ref-is-glvalue && bidirectional_range<Base> &&
5762
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
5763
+ ```
5764
+
5765
+ *Effects:* Equivalent to:
5766
+
5767
+ ``` cpp
5768
+ if (outer_it_ == ranges::end(parent_->base_)) {
5769
+ auto&& inner = *--outer_it_;
5770
+ inner_it_.emplace<1>(ranges::end(inner));
5771
+ }
5772
+
5773
+ while (true) {
5774
+ if (inner_it_.index() == 0) {
5775
+ auto& it = std::get<0>(inner_it_);
5776
+ if (it == ranges::begin(parent_->pattern_)) {
5777
+ auto&& inner = *--outer_it_;
5778
+ inner_it_.emplace<1>(ranges::end(inner));
5779
+ } else {
5780
+ break;
5781
+ }
5782
+ } else {
5783
+ auto& it = std::get<1>(inner_it_);
5784
+ auto&& inner = *outer_it_;
5785
+ if (it == ranges::begin(inner)) {
5786
+ inner_it_.emplace<0>(ranges::end(parent_->pattern_));
5787
+ } else {
5788
+ break;
5789
+ }
5790
+ }
5791
+ }
5792
+ visit([](auto& it){ --it; }, inner_it_);
5793
+ return *this;
5794
+ ```
5795
+
5796
+ ``` cpp
5797
+ constexpr iterator operator--(int)
5798
+ requires ref-is-glvalue && bidirectional_range<Base> &&
5799
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
5800
+ ```
5801
+
5802
+ *Effects:* Equivalent to:
5803
+
5804
+ ``` cpp
5805
+ iterator tmp = *this;
5806
+ --*this;
5807
+ return tmp;
5808
+ ```
5809
+
5810
+ ``` cpp
5811
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
5812
+ requires ref-is-glvalue && forward_range<Base> &&
5813
+ equality_comparable<InnerIter>;
5814
+ ```
5815
+
5816
+ *Effects:* Equivalent to:
5817
+
5818
+ ``` cpp
5819
+ return x.outer_it_ == y.outer_it_ && x.inner_it_ == y.inner_it_;
5820
+ ```
5821
+
5822
+ #### Class template `join_with_view::sentinel` <a id="range.join.with.sentinel">[[range.join.with.sentinel]]</a>
5823
+
5824
+ ``` cpp
5825
+ namespace std::ranges {
5826
+ template<input_range V, forward_range Pattern>
5827
+ requires view<V> && input_range<range_reference_t<V>>
5828
+ && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
5829
+ template<bool Const>
5830
+ class join_with_view<V, Pattern>::sentinel {
5831
+ using Parent = maybe-const<Const, join_with_view>; // exposition only
5832
+ using Base = maybe-const<Const, V>; // exposition only
5833
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
5834
+
5835
+ constexpr explicit sentinel(Parent& parent); // exposition only
5836
+
5837
+ public:
5838
+ sentinel() = default;
5839
+ constexpr sentinel(sentinel<!Const> s)
5840
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
5841
+
5842
+ template<bool OtherConst>
5843
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
5844
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5845
  };
5846
  }
5847
  ```
5848
 
5849
  ``` cpp
 
5858
  ```
5859
 
5860
  *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
5861
 
5862
  ``` cpp
5863
+ template<bool OtherConst>
5864
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
5865
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
5866
  ```
5867
 
5868
+ *Effects:* Equivalent to: `return x.`*`outer`*`() == y.`*`end_`*`;`
5869
 
5870
+ ### Lazy split view <a id="range.lazy.split">[[range.lazy.split]]</a>
5871
 
5872
+ #### Overview <a id="range.lazy.split.overview">[[range.lazy.split.overview]]</a>
5873
 
5874
+ `lazy_split_view` takes a view and a delimiter, and splits the view into
5875
  subranges on the delimiter. The delimiter can be a single element or a
5876
+ view of elements.
5877
 
5878
+ The name `views::lazy_split` denotes a range adaptor object
5879
  [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
5880
+ expression `views::lazy_split(E, F)` is expression-equivalent to
5881
+ `lazy_split_view(E, F)`.
5882
 
5883
  [*Example 1*:
5884
 
5885
  ``` cpp
5886
  string str{"the quick brown fox"};
5887
+ for (auto word : str | views::lazy_split(' ')) {
 
5888
  for (char ch : word)
5889
  cout << ch;
5890
  cout << '*';
5891
  }
5892
+ // The above prints the*quick*brown*fox*
5893
  ```
5894
 
5895
  — *end example*]
5896
 
5897
+ #### Class template `lazy_split_view` <a id="range.lazy.split.view">[[range.lazy.split.view]]</a>
5898
 
5899
  ``` cpp
5900
  namespace std::ranges {
5901
  template<auto> struct require-constant; // exposition only
5902
 
 
5908
 
5909
  template<input_range V, forward_range Pattern>
5910
  requires view<V> && view<Pattern> &&
5911
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
5912
  (forward_range<V> || tiny-range<Pattern>)
5913
+ class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> {
5914
  private:
5915
  V base_ = V(); // exposition only
5916
  Pattern pattern_ = Pattern(); // exposition only
5917
+
5918
+ non-propagating-cache<iterator_t<V>> current_; // exposition only, present only
5919
+ // if forward_range<V> is false
5920
+
5921
+ // [range.lazy.split.outer], class template lazy_split_view::outer-iterator
5922
  template<bool> struct outer-iterator; // exposition only
5923
+
5924
+ // [range.lazy.split.inner], class template lazy_split_view::inner-iterator
5925
  template<bool> struct inner-iterator; // exposition only
5926
+
5927
  public:
5928
+ lazy_split_view()
5929
+ requires default_initializable<V> && default_initializable<Pattern> = default;
5930
+ constexpr explicit lazy_split_view(V base, Pattern pattern);
5931
 
5932
  template<input_range R>
5933
  requires constructible_from<V, views::all_t<R>> &&
5934
  constructible_from<Pattern, single_view<range_value_t<R>>>
5935
+ constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);
5936
 
5937
  constexpr V base() const & requires copy_constructible<V> { return base_; }
5938
  constexpr V base() && { return std::move(base_); }
5939
 
5940
  constexpr auto begin() {
5941
+ if constexpr (forward_range<V>) {
5942
+ return outer-iterator<simple-view<V> && simple-view<Pattern>>
5943
+ {*this, ranges::begin(base_)};
5944
+ } else {
5945
  current_ = ranges::begin(base_);
5946
  return outer-iterator<false>{*this};
5947
  }
5948
  }
5949
 
5950
  constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
5951
  return outer-iterator<true>{*this, ranges::begin(base_)};
5952
  }
5953
 
5954
  constexpr auto end() requires forward_range<V> && common_range<V> {
5955
+ return outer-iterator<simple-view<V> && simple-view<Pattern>>
5956
+ {*this, ranges::end(base_)};
5957
  }
5958
 
5959
  constexpr auto end() const {
5960
  if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
5961
  return outer-iterator<true>{*this, ranges::end(base_)};
 
5963
  return default_sentinel;
5964
  }
5965
  };
5966
 
5967
  template<class R, class P>
5968
+ lazy_split_view(R&&, P&&) -> lazy_split_view<views::all_t<R>, views::all_t<P>>;
5969
 
5970
  template<input_range R>
5971
+ lazy_split_view(R&&, range_value_t<R>)
5972
+ -> lazy_split_view<views::all_t<R>, single_view<range_value_t<R>>>;
5973
  }
5974
  ```
5975
 
5976
  ``` cpp
5977
+ constexpr explicit lazy_split_view(V base, Pattern pattern);
5978
  ```
5979
 
5980
  *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
5981
  with `std::move(pattern)`.
5982
 
5983
  ``` cpp
5984
  template<input_range R>
5985
  requires constructible_from<V, views::all_t<R>> &&
5986
  constructible_from<Pattern, single_view<range_value_t<R>>>
5987
+ constexpr explicit lazy_split_view(R&& r, range_value_t<R> e);
5988
  ```
5989
 
5990
  *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
5991
+ and *pattern\_* with `views::single(std::move(e))`.
5992
 
5993
+ #### Class template `lazy_split_view::outer-iterator` <a id="range.lazy.split.outer">[[range.lazy.split.outer]]</a>
5994
 
5995
  ``` cpp
5996
  namespace std::ranges {
5997
  template<input_range V, forward_range Pattern>
5998
  requires view<V> && view<Pattern> &&
5999
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
6000
  (forward_range<V> || tiny-range<Pattern>)
6001
  template<bool Const>
6002
+ struct lazy_split_view<V, Pattern>::outer-iterator {
6003
  private:
6004
+ using Parent = maybe-const<Const, lazy_split_view>; // exposition only
6005
+ using Base = maybe-const<Const, V>; // exposition only
 
 
6006
  Parent* parent_ = nullptr; // exposition only
6007
+
6008
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only, present only
6009
+ // if V models forward_range
6010
+
6011
+ bool trailing_empty_ = false; // exposition only
6012
 
6013
  public:
6014
  using iterator_concept =
6015
  conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
6016
+
6017
+ using iterator_category = input_iterator_tag; // present only if Base
6018
+ // models forward_range
6019
+
6020
+ // [range.lazy.split.outer.value], class lazy_split_view::outer-iterator::value_type
6021
  struct value_type;
6022
  using difference_type = range_difference_t<Base>;
6023
 
6024
  outer-iterator() = default;
6025
  constexpr explicit outer-iterator(Parent& parent)
 
6047
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
6048
  };
6049
  }
6050
  ```
6051
 
6052
+ Many of the specifications in [[range.lazy.split]] refer to the notional
6053
+ member *current* of *`outer-iterator`*. *current* is equivalent to
6054
+ *`current_`* if `V` models `forward_range`, and `*parent_->current_`
6055
+ otherwise.
6056
 
6057
  ``` cpp
6058
  constexpr explicit outer-iterator(Parent& parent)
6059
  requires (!forward_range<Base>);
6060
  ```
 
6089
 
6090
  *Effects:* Equivalent to:
6091
 
6092
  ``` cpp
6093
  const auto end = ranges::end(parent_->base_);
6094
+ if (current == end) {
6095
+ trailing_empty_ = false;
6096
+ return *this;
6097
+ }
6098
  const auto [pbegin, pend] = subrange{parent_->pattern_};
6099
  if (pbegin == pend) ++current;
6100
+ else if constexpr (tiny-range<Pattern>) {
6101
+ current = ranges::find(std::move(current), end, *pbegin);
6102
+ if (current != end) {
6103
+ ++current;
6104
+ if (current == end)
6105
+ trailing_empty_ = true;
6106
+ }
6107
+ }
6108
  else {
6109
  do {
6110
+ auto [b, p] = ranges::mismatch(current, end, pbegin, pend);
 
6111
  if (p == pend) {
6112
+ current = b;
6113
+ if (current == end)
6114
+ trailing_empty_ = true;
6115
  break; // The pattern matched; skip it
6116
  }
6117
  } while (++current != end);
6118
  }
6119
  return *this;
 
6122
  ``` cpp
6123
  friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
6124
  requires forward_range<Base>;
6125
  ```
6126
 
6127
+ *Effects:* Equivalent to:
6128
+
6129
+ ``` cpp
6130
+ return x.current_ == y.current_ && x.trailing_empty_ == y.trailing_empty_;
6131
+ ```
6132
 
6133
  ``` cpp
6134
  friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
6135
  ```
6136
 
6137
  *Effects:* Equivalent to:
 
6138
 
6139
+ ``` cpp
6140
+ return x.current == ranges::end(x.parent_->base_) && !x.trailing_empty_;
6141
+ ```
6142
+
6143
+ #### Class `lazy_split_view::outer-iterator::value_type` <a id="range.lazy.split.outer.value">[[range.lazy.split.outer.value]]</a>
6144
 
6145
  ``` cpp
6146
  namespace std::ranges {
6147
  template<input_range V, forward_range Pattern>
6148
  requires view<V> && view<Pattern> &&
6149
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
6150
  (forward_range<V> || tiny-range<Pattern>)
6151
  template<bool Const>
6152
+ struct lazy_split_view<V, Pattern>::outer-iterator<Const>::value_type
6153
  : view_interface<value_type> {
6154
  private:
6155
  outer-iterator i_ = outer-iterator(); // exposition only
6156
+
6157
  public:
6158
  value_type() = default;
6159
  constexpr explicit value_type(outer-iterator i);
6160
 
6161
+ constexpr inner-iterator<Const> begin() const;
6162
+ constexpr default_sentinel_t end() const noexcept;
 
6163
  };
6164
  }
6165
  ```
6166
 
6167
  ``` cpp
 
6169
  ```
6170
 
6171
  *Effects:* Initializes *i\_* with `std::move(i)`.
6172
 
6173
  ``` cpp
6174
+ constexpr inner-iterator<Const> begin() const;
6175
  ```
6176
 
6177
  *Effects:* Equivalent to:
6178
  `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
6179
 
6180
  ``` cpp
6181
+ constexpr default_sentinel_t end() const noexcept;
 
 
 
 
 
 
 
6182
  ```
6183
 
6184
  *Effects:* Equivalent to: `return default_sentinel;`
6185
 
6186
+ #### Class template `lazy_split_view::inner-iterator` <a id="range.lazy.split.inner">[[range.lazy.split.inner]]</a>
6187
 
6188
  ``` cpp
6189
  namespace std::ranges {
6190
  template<input_range V, forward_range Pattern>
6191
  requires view<V> && view<Pattern> &&
6192
  indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
6193
  (forward_range<V> || tiny-range<Pattern>)
6194
  template<bool Const>
6195
+ struct lazy_split_view<V, Pattern>::inner-iterator {
6196
  private:
6197
+ using Base = maybe-const<Const, V>; // exposition only
6198
  outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
6199
  bool incremented_ = false; // exposition only
6200
+
6201
  public:
6202
  using iterator_concept = typename outer-iterator<Const>::iterator_concept;
6203
+
6204
+ using iterator_category = see belownc; // present only if Base
6205
+ // models forward_range
6206
  using value_type = range_value_t<Base>;
6207
  using difference_type = range_difference_t<Base>;
6208
 
6209
  inner-iterator() = default;
6210
  constexpr explicit inner-iterator(outer-iterator<Const> i);
6211
 
6212
+ constexpr const iterator_t<Base>& base() const & noexcept;
6213
+ constexpr iterator_t<Base> base() && requires forward_range<V>;
6214
+
6215
  constexpr decltype(auto) operator*() const { return *i_.current; }
6216
 
6217
  constexpr inner-iterator& operator++();
6218
  constexpr decltype(auto) operator++(int) {
6219
+ if constexpr (forward_range<Base>) {
6220
  auto tmp = *this;
6221
  ++*this;
6222
  return tmp;
6223
  } else
6224
  ++*this;
 
6239
  requires indirectly_swappable<iterator_t<Base>>;
6240
  };
6241
  }
6242
  ```
6243
 
6244
+ If *`Base`* does not model `forward_range` there is no member
6245
+ `iterator_category`. Otherwise, the *typedef-name* `iterator_category`
6246
+ denotes:
6247
 
6248
  - `forward_iterator_tag` if
6249
  `iterator_traits<iterator_t<Base>>::iterator_category` models
6250
  `derived_from<forward_iterator_tag>`;
6251
  - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
 
6254
  constexpr explicit inner-iterator(outer-iterator<Const> i);
6255
  ```
6256
 
6257
  *Effects:* Initializes *i\_* with `std::move(i)`.
6258
 
6259
+ ``` cpp
6260
+ constexpr const iterator_t<Base>& base() const & noexcept;
6261
+ ```
6262
+
6263
+ *Effects:* Equivalent to: `return `*`i_`*`.`*`current`*`;`
6264
+
6265
+ ``` cpp
6266
+ constexpr iterator_t<Base> base() && requires forward_range<V>;
6267
+ ```
6268
+
6269
+ *Effects:* Equivalent to: `return std::move(`*`i_`*`.`*`current`*`);`
6270
+
6271
  ``` cpp
6272
  constexpr inner-iterator& operator++();
6273
  ```
6274
 
6275
  *Effects:* Equivalent to:
 
6326
  ```
6327
 
6328
  *Effects:* Equivalent to
6329
  `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
6330
 
6331
+ ### Split view <a id="range.split">[[range.split]]</a>
6332
+
6333
+ #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
6334
+
6335
+ `split_view` takes a view and a delimiter, and splits the view into
6336
+ `subrange`s on the delimiter. The delimiter can be a single element or a
6337
+ view of elements.
6338
+
6339
+ The name `views::split` denotes a range adaptor object
6340
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
6341
+ expression `views::split(E, F)` is expression-equivalent to
6342
+ `split_view(E, F)`.
6343
+
6344
+ [*Example 1*:
6345
+
6346
+ ``` cpp
6347
+ string str{"the quick brown fox"};
6348
+ for (auto word : views::split(str, ' ')) {
6349
+ cout << string_view(word) << '*';
6350
+ }
6351
+ // The above prints the*quick*brown*fox*
6352
+ ```
6353
+
6354
+ — *end example*]
6355
+
6356
+ #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
6357
+
6358
+ ``` cpp
6359
+ namespace std::ranges {
6360
+ template<forward_range V, forward_range Pattern>
6361
+ requires view<V> && view<Pattern> &&
6362
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
6363
+ class split_view : public view_interface<split_view<V, Pattern>> {
6364
+ private:
6365
+ V base_ = V(); // exposition only
6366
+ Pattern pattern_ = Pattern(); // exposition only
6367
+
6368
+ // [range.split.iterator], class split_view::iterator
6369
+ struct iterator; // exposition only
6370
+
6371
+ // [range.split.sentinel], class split_view::sentinel
6372
+ struct sentinel; // exposition only
6373
+
6374
+ public:
6375
+ split_view()
6376
+ requires default_initializable<V> && default_initializable<Pattern> = default;
6377
+ constexpr explicit split_view(V base, Pattern pattern);
6378
+
6379
+ template<forward_range R>
6380
+ requires constructible_from<V, views::all_t<R>> &&
6381
+ constructible_from<Pattern, single_view<range_value_t<R>>>
6382
+ constexpr explicit split_view(R&& r, range_value_t<R> e);
6383
+
6384
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
6385
+ constexpr V base() && { return std::move(base_); }
6386
+
6387
+ constexpr iterator begin();
6388
+
6389
+ constexpr auto end() {
6390
+ if constexpr (common_range<V>) {
6391
+ return iterator{*this, ranges::end(base_), {}};
6392
+ } else {
6393
+ return sentinel{*this};
6394
+ }
6395
+ }
6396
+
6397
+ constexpr subrange<iterator_t<V>> find-next(iterator_t<V>); // exposition only
6398
+ };
6399
+
6400
+ template<class R, class P>
6401
+ split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
6402
+
6403
+ template<forward_range R>
6404
+ split_view(R&&, range_value_t<R>)
6405
+ -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
6406
+ }
6407
+ ```
6408
+
6409
+ ``` cpp
6410
+ constexpr explicit split_view(V base, Pattern pattern);
6411
+ ```
6412
+
6413
+ *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
6414
+ with `std::move(pattern)`.
6415
+
6416
+ ``` cpp
6417
+ template<forward_range R>
6418
+ requires constructible_from<V, views::all_t<R>> &&
6419
+ constructible_from<Pattern, single_view<range_value_t<R>>>
6420
+ constexpr explicit split_view(R&& r, range_value_t<R> e);
6421
+ ```
6422
+
6423
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
6424
+ and *pattern\_* with `views::single(std::move(e))`.
6425
+
6426
+ ``` cpp
6427
+ constexpr iterator begin();
6428
+ ```
6429
+
6430
+ *Returns:*
6431
+ `{*this, ranges::begin(`*`base_`*`), `*`find-next`*`(ranges::begin(`*`base_`*`))}`.
6432
+
6433
+ *Remarks:* In order to provide the amortized constant time complexity
6434
+ required by the `range` concept, this function caches the result within
6435
+ the `split_view` for use on subsequent calls.
6436
+
6437
+ ``` cpp
6438
+ constexpr subrange<iterator_t<V>> find-next(iterator_t<V> it);
6439
+ ```
6440
+
6441
+ *Effects:* Equivalent to:
6442
+
6443
+ ``` cpp
6444
+ auto [b, e] = ranges::search(subrange(it, ranges::end(base_)), pattern_);
6445
+ if (b != ranges::end(base_) && ranges::empty(pattern_)) {
6446
+ ++b;
6447
+ ++e;
6448
+ }
6449
+ return {b, e};
6450
+ ```
6451
+
6452
+ #### Class `split_view::iterator` <a id="range.split.iterator">[[range.split.iterator]]</a>
6453
+
6454
+ ``` cpp
6455
+ namespace std::ranges {
6456
+ template<forward_range V, forward_range Pattern>
6457
+ requires view<V> && view<Pattern> &&
6458
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
6459
+ class split_view<V, Pattern>::iterator {
6460
+ private:
6461
+ split_view* parent_ = nullptr; // exposition only
6462
+ iterator_t<V> cur_ = iterator_t<V>(); // exposition only
6463
+ subrange<iterator_t<V>> next_ = subrange<iterator_t<V>>(); // exposition only
6464
+ bool trailing_empty_ = false; // exposition only
6465
+
6466
+ public:
6467
+ using iterator_concept = forward_iterator_tag;
6468
+ using iterator_category = input_iterator_tag;
6469
+ using value_type = subrange<iterator_t<V>>;
6470
+ using difference_type = range_difference_t<V>;
6471
+
6472
+ iterator() = default;
6473
+ constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
6474
+
6475
+ constexpr iterator_t<V> base() const;
6476
+ constexpr value_type operator*() const;
6477
+
6478
+ constexpr iterator& operator++();
6479
+ constexpr iterator operator++(int);
6480
+
6481
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
6482
+ };
6483
+ }
6484
+ ```
6485
+
6486
+ ``` cpp
6487
+ constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_t<V>> next);
6488
+ ```
6489
+
6490
+ *Effects:* Initializes *parent\_* with `addressof(parent)`, *cur\_* with
6491
+ `std::move(current)`, and *next\_* with `std::move(next)`.
6492
+
6493
+ ``` cpp
6494
+ constexpr iterator_t<V> base() const;
6495
+ ```
6496
+
6497
+ *Effects:* Equivalent to `return `*`cur_`*`;`
6498
+
6499
+ ``` cpp
6500
+ constexpr value_type operator*() const;
6501
+ ```
6502
+
6503
+ *Effects:* Equivalent to `return {`*`cur_`*`, `*`next_`*`.begin()};`
6504
+
6505
+ ``` cpp
6506
+ constexpr iterator& operator++();
6507
+ ```
6508
+
6509
+ *Effects:* Equivalent to:
6510
+
6511
+ ``` cpp
6512
+ cur_ = next_.begin();
6513
+ if (cur_ != ranges::end(parent_->base_)) {
6514
+ cur_ = next_.end();
6515
+ if (cur_ == ranges::end(parent_->base_)) {
6516
+ trailing_empty_ = true;
6517
+ next_ = {cur_, cur_};
6518
+ } else {
6519
+ next_ = parent_->find-next(cur_);
6520
+ }
6521
+ } else {
6522
+ trailing_empty_ = false;
6523
+ }
6524
+ return *this;
6525
+ ```
6526
+
6527
+ ``` cpp
6528
+ constexpr iterator operator++(int);
6529
+ ```
6530
+
6531
+ *Effects:* Equivalent to:
6532
+
6533
+ ``` cpp
6534
+ auto tmp = *this;
6535
+ ++*this;
6536
+ return tmp;
6537
+ ```
6538
+
6539
+ ``` cpp
6540
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
6541
+ ```
6542
+
6543
+ *Effects:* Equivalent to:
6544
+
6545
+ ``` cpp
6546
+ return x.cur_ == y.cur_ && x.trailing_empty_ == y.trailing_empty_;
6547
+ ```
6548
+
6549
+ #### Class `split_view::sentinel` <a id="range.split.sentinel">[[range.split.sentinel]]</a>
6550
+
6551
+ ``` cpp
6552
+ namespace std::ranges {
6553
+ template<forward_range V, forward_range Pattern>
6554
+ requires view<V> && view<Pattern> &&
6555
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>
6556
+ struct split_view<V, Pattern>::sentinel {
6557
+ private:
6558
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
6559
+
6560
+ public:
6561
+ sentinel() = default;
6562
+ constexpr explicit sentinel(split_view& parent);
6563
+
6564
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
6565
+ };
6566
+ }
6567
+ ```
6568
+
6569
+ ``` cpp
6570
+ constexpr explicit sentinel(split_view& parent);
6571
+ ```
6572
+
6573
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
6574
+
6575
+ ``` cpp
6576
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
6577
+ ```
6578
+
6579
+ *Effects:* Equivalent to:
6580
+ `return x.`*`cur_`*` == y.`*`end_`*` && !x.`*`trailing_empty_`*`;`
6581
+
6582
  ### Counted view <a id="range.counted">[[range.counted]]</a>
6583
 
6584
+ A counted view presents a view of the elements of the counted range
6585
  [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
6586
  non-negative integer `n`.
6587
 
6588
  The name `views::counted` denotes a customization point object
6589
  [[customization.point.object]]. Let `E` and `F` be expressions, let `T`
 
6596
  instantiation. — *end note*]
6597
 
6598
  Otherwise, `views::counted(E, F)` is expression-equivalent to:
6599
 
6600
  - If `T` models `contiguous_iterator`, then
6601
+ `span(to_address(E), static_cast<size_t>(static_-{}cast<D>(F)))`.
6602
  - Otherwise, if `T` models `random_access_iterator`, then
6603
+ `subrange(E, E + static_cast<D>(F))`, except that `E` is evaluated
6604
  only once.
6605
+ - Otherwise, `subrange(counted_iterator(E, F), default_sentinel)`.
6606
 
6607
  ### Common view <a id="range.common">[[range.common]]</a>
6608
 
6609
  #### Overview <a id="range.common.overview">[[range.common.overview]]</a>
6610
 
6611
+ `common_view` takes a view which has different types for its iterator
6612
+ and sentinel and turns it into a view of the same elements with an
6613
  iterator and sentinel of the same type.
6614
 
6615
  [*Note 1*: `common_view` is useful for calling legacy algorithms that
6616
  expect a range’s iterator and sentinel types to be the
6617
  same. — *end note*]
 
6631
  template<class ForwardIterator>
6632
  size_t count(ForwardIterator first, ForwardIterator last);
6633
 
6634
  template<forward_range R>
6635
  void my_algo(R&& r) {
6636
+ auto&& common = views::common(r);
6637
  auto cnt = count(common.begin(), common.end());
6638
  // ...
6639
  }
6640
  ```
6641
 
 
6648
  template<view V>
6649
  requires (!common_range<V> && copyable<iterator_t<V>>)
6650
  class common_view : public view_interface<common_view<V>> {
6651
  private:
6652
  V base_ = V(); // exposition only
6653
+
6654
  public:
6655
+ common_view() requires default_initializable<V> = default;
6656
 
6657
  constexpr explicit common_view(V r);
6658
 
 
 
 
 
6659
  constexpr V base() const & requires copy_constructible<V> { return base_; }
6660
  constexpr V base() && { return std::move(base_); }
6661
 
6662
  constexpr auto begin() {
6663
  if constexpr (random_access_range<V> && sized_range<V>)
 
6673
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
6674
  }
6675
 
6676
  constexpr auto end() {
6677
  if constexpr (random_access_range<V> && sized_range<V>)
6678
+ return ranges::begin(base_) + ranges::distance(base_);
6679
  else
6680
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
6681
  }
6682
 
6683
  constexpr auto end() const requires range<const V> {
6684
  if constexpr (random_access_range<const V> && sized_range<const V>)
6685
+ return ranges::begin(base_) + ranges::distance(base_);
6686
  else
6687
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
6688
  }
6689
 
6690
  constexpr auto size() requires sized_range<V> {
 
6704
  constexpr explicit common_view(V base);
6705
  ```
6706
 
6707
  *Effects:* Initializes *base\_* with `std::move(base)`.
6708
 
 
 
 
 
 
 
 
 
6709
  ### Reverse view <a id="range.reverse">[[range.reverse]]</a>
6710
 
6711
  #### Overview <a id="range.reverse.overview">[[range.reverse.overview]]</a>
6712
 
6713
+ `reverse_view` takes a bidirectional view and produces another view that
6714
+ iterates the same elements in reverse order.
6715
 
6716
  The name `views::reverse` denotes a range adaptor object
6717
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
6718
  `views::reverse(E)` is expression-equivalent to:
6719
 
6720
  - If the type of `E` is a (possibly cv-qualified) specialization of
6721
  `reverse_view`, equivalent to `E.base()`.
6722
+ - Otherwise, if the type of `E` is cv
6723
+ `subrange<reverse_iterator<I>, reverse_iterator<I>, K>` for some
6724
+ iterator type `I` and value `K` of type `subrange_kind`,
 
 
 
6725
  - if `K` is `subrange_kind::sized`, equivalent to:
6726
  ``` cpp
6727
  subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
6728
  ```
6729
  - otherwise, equivalent to:
 
6736
 
6737
  [*Example 1*:
6738
 
6739
  ``` cpp
6740
  vector<int> is {0,1,2,3,4};
6741
+ for (int i : is | views::reverse)
6742
+ cout << i << ' '; // prints 4 3 2 1 0
 
6743
  ```
6744
 
6745
  — *end example*]
6746
 
6747
  #### Class template `reverse_view` <a id="range.reverse.view">[[range.reverse.view]]</a>
 
6751
  template<view V>
6752
  requires bidirectional_range<V>
6753
  class reverse_view : public view_interface<reverse_view<V>> {
6754
  private:
6755
  V base_ = V(); // exposition only
6756
+
6757
  public:
6758
+ reverse_view() requires default_initializable<V> = default;
6759
 
6760
  constexpr explicit reverse_view(V r);
6761
 
6762
  constexpr V base() const & requires copy_constructible<V> { return base_; }
6763
  constexpr V base() && { return std::move(base_); }
 
6770
  constexpr auto end() const requires common_range<const V>;
6771
 
6772
  constexpr auto size() requires sized_range<V> {
6773
  return ranges::size(base_);
6774
  }
6775
+
6776
  constexpr auto size() const requires sized_range<const V> {
6777
  return ranges::size(base_);
6778
  }
6779
  };
6780
 
 
6807
  constexpr reverse_iterator<iterator_t<V>> begin() requires common_range<V>;
6808
  constexpr auto begin() const requires common_range<const V>;
6809
  ```
6810
 
6811
  *Effects:* Equivalent to:
6812
+ `return make_reverse_iterator(ranges::end(`*`base_`*`));`
6813
 
6814
  ``` cpp
6815
  constexpr reverse_iterator<iterator_t<V>> end();
6816
  constexpr auto end() const requires common_range<const V>;
6817
  ```
6818
 
6819
  *Effects:* Equivalent to:
6820
+ `return make_reverse_iterator(ranges::begin(`*`base_`*`));`
6821
+
6822
+ ### As const view <a id="range.as.const">[[range.as.const]]</a>
6823
+
6824
+ #### Overview <a id="range.as.const.overview">[[range.as.const.overview]]</a>
6825
+
6826
+ `as_const_view` presents a view of an underlying sequence as constant.
6827
+ That is, the elements of an `as_const_view` cannot be modified.
6828
+
6829
+ The name `views::as_const` denotes a range adaptor object
6830
+ [[range.adaptor.object]]. Let `E` be an expression, let `T` be
6831
+ `decltype((E))`, and let `U` be `remove_cvref_t<T>`. The expression
6832
+ `views::as_const(E)` is expression-equivalent to:
6833
+
6834
+ - If `views::all_t<T>` models `constant_range`, then `views::all(E)`.
6835
+ - Otherwise, if `U` denotes `empty_view<X>` for some type `X`, then
6836
+ `auto(views::empty<const X>)`.
6837
+ - Otherwise, if `U` denotes `span<X, Extent>` for some type `X` and some
6838
+ extent `Extent`, then `span<const X, Extent>(E)`.
6839
+ - Otherwise, if `U` denotes `ref_view<X>` for some type `X` and
6840
+ `const X` models `constant_range`, then
6841
+ `ref_view(static_cast<const X&>(E.base()))`.
6842
+ - Otherwise, if `E` is an lvalue, `const U` models `constant_range`, and
6843
+ `U` does not model `view`, then `ref_view(static_cast<const U&>(E))`.
6844
+ - Otherwise, `as_const_view(E)`.
6845
+
6846
+ [*Example 1*:
6847
+
6848
+ ``` cpp
6849
+ template<constant_range R>
6850
+ void cant_touch_this(R&&);
6851
+
6852
+ vector<char> hammer = {'m', 'c'};
6853
+ span<char> beat = hammer;
6854
+ cant_touch_this(views::as_const(beat)); // will not modify the elements of hammer
6855
+ ```
6856
+
6857
+ — *end example*]
6858
+
6859
+ #### Class template `as_const_view` <a id="range.as.const.view">[[range.as.const.view]]</a>
6860
+
6861
+ ``` cpp
6862
+ namespace std::ranges {
6863
+ template<view V>
6864
+ requires input_range<V>
6865
+ class as_const_view : public view_interface<as_const_view<V>> {
6866
+ V base_ = V(); // exposition only
6867
+
6868
+ public:
6869
+ as_const_view() requires default_initializable<V> = default;
6870
+ constexpr explicit as_const_view(V base);
6871
+
6872
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
6873
+ constexpr V base() && { return std::move(base_); }
6874
+
6875
+ constexpr auto begin() requires (!simple-view<V>) { return ranges::cbegin(base_); }
6876
+ constexpr auto begin() const requires range<const V> { return ranges::cbegin(base_); }
6877
+
6878
+ constexpr auto end() requires (!simple-view<V>) { return ranges::cend(base_); }
6879
+ constexpr auto end() const requires range<const V> { return ranges::cend(base_); }
6880
+
6881
+ constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
6882
+ constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
6883
+ };
6884
+
6885
+ template<class R>
6886
+ as_const_view(R&&) -> as_const_view<views::all_t<R>>;
6887
+ }
6888
+ ```
6889
+
6890
+ ``` cpp
6891
+ constexpr explicit as_const_view(V base);
6892
+ ```
6893
+
6894
+ *Effects:* Initializes *base\_* with `std::move(base)`.
6895
 
6896
  ### Elements view <a id="range.elements">[[range.elements]]</a>
6897
 
6898
  #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
6899
 
6900
+ `elements_view` takes a view of tuple-like values and a `size_t`, and
6901
+ produces a view with a value-type of the Nᵗʰ element of the adapted
6902
+ view’s value-type.
6903
 
6904
  The name `views::elements<N>` denotes a range adaptor object
6905
  [[range.adaptor.object]]. Given a subexpression `E` and constant
6906
  expression `N`, the expression `views::elements<N>(E)` is
6907
  expression-equivalent to
 
6909
 
6910
  [*Example 1*:
6911
 
6912
  ``` cpp
6913
  auto historical_figures = map{
6914
+ pair{"Lovelace"sv, 1815},
6915
  {"Turing"sv, 1912},
6916
  {"Babbage"sv, 1791},
6917
  {"Hamilton"sv, 1936}
6918
  };
6919
 
 
6928
  }
6929
  ```
6930
 
6931
  — *end example*]
6932
 
6933
+ `keys_view` is an alias for `elements_view<R, 0>`, and is useful for
6934
+ extracting keys from associative containers.
6935
 
6936
  [*Example 2*:
6937
 
6938
  ``` cpp
6939
+ auto names = historical_figures | views::keys;
6940
  for (auto&& name : names) {
6941
  cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
6942
  }
6943
  ```
6944
 
6945
  — *end example*]
6946
 
6947
+ `values_view` is an alias for `elements_view<R, 1>`, and is useful for
6948
+ extracting values from associative containers.
6949
 
6950
  [*Example 3*:
6951
 
6952
  ``` cpp
6953
  auto is_even = [](const auto x) { return x % 2 == 0; };
6954
+ cout << ranges::count_if(historical_figures | views::values, is_even); // prints 2
6955
  ```
6956
 
6957
  — *end example*]
6958
 
6959
  #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
6960
 
6961
  ``` cpp
6962
  namespace std::ranges {
6963
  template<class T, size_t N>
6964
  concept has-tuple-element = // exposition only
6965
+ tuple-like<T> && N < tuple_size_v<T>;
 
 
 
 
 
6966
 
6967
+ template<class T, size_t N>
6968
+ concept returnable-element = // exposition only
6969
+ is_reference_v<T> || move_constructible<tuple_element_t<N, T>>;
6970
 
6971
  template<input_range V, size_t N>
6972
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
6973
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
6974
+ returnable-element<range_reference_t<V>, N>
6975
  class elements_view : public view_interface<elements_view<V, N>> {
6976
  public:
6977
+ elements_view() requires default_initializable<V> = default;
6978
  constexpr explicit elements_view(V base);
6979
 
6980
  constexpr V base() const & requires copy_constructible<V> { return base_; }
6981
  constexpr V base() && { return std::move(base_); }
6982
 
6983
  constexpr auto begin() requires (!simple-view<V>)
6984
  { return iterator<false>(ranges::begin(base_)); }
6985
 
6986
+ constexpr auto begin() const requires range<const V>
6987
  { return iterator<true>(ranges::begin(base_)); }
6988
 
6989
+ constexpr auto end() requires (!simple-view<V> && !common_range<V>)
6990
  { return sentinel<false>{ranges::end(base_)}; }
6991
 
6992
+ constexpr auto end() requires (!simple-view<V> && common_range<V>)
6993
  { return iterator<false>{ranges::end(base_)}; }
6994
 
6995
  constexpr auto end() const requires range<const V>
6996
  { return sentinel<true>{ranges::end(base_)}; }
6997
 
 
7004
  constexpr auto size() const requires sized_range<const V>
7005
  { return ranges::size(base_); }
7006
 
7007
  private:
7008
  // [range.elements.iterator], class template elements_view::iterator
7009
+ template<bool> class iterator; // exposition only
7010
+
7011
  // [range.elements.sentinel], class template elements_view::sentinel
7012
+ template<bool> class sentinel; // exposition only
7013
+
7014
  V base_ = V(); // exposition only
7015
  };
7016
  }
7017
  ```
7018
 
 
7026
 
7027
  ``` cpp
7028
  namespace std::ranges {
7029
  template<input_range V, size_t N>
7030
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
7031
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
7032
+ returnable-element<range_reference_t<V>, N>
7033
  template<bool Const>
7034
+ class elements_view<V, N>::iterator {
7035
+ using Base = maybe-const<Const, V>; // exposition only
7036
+
7037
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
7038
+
7039
+ static constexpr decltype(auto) get-element(const iterator_t<Base>& i); // exposition only
7040
 
 
7041
  public:
7042
+ using iterator_concept = see below;
7043
+ using iterator_category = see below; // not always present
7044
  using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
7045
  using difference_type = range_difference_t<Base>;
7046
 
7047
+ iterator() requires default_initializable<iterator_t<Base>> = default;
7048
  constexpr explicit iterator(iterator_t<Base> current);
7049
  constexpr iterator(iterator<!Const> i)
7050
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
7051
 
7052
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
7053
  constexpr iterator_t<Base> base() &&;
7054
 
7055
  constexpr decltype(auto) operator*() const
7056
+ { return get-element(current_); }
7057
 
7058
  constexpr iterator& operator++();
7059
+ constexpr void operator++(int);
7060
  constexpr iterator operator++(int) requires forward_range<Base>;
7061
 
7062
  constexpr iterator& operator--() requires bidirectional_range<Base>;
7063
  constexpr iterator operator--(int) requires bidirectional_range<Base>;
7064
 
 
7067
  constexpr iterator& operator-=(difference_type x)
7068
  requires random_access_range<Base>;
7069
 
7070
  constexpr decltype(auto) operator[](difference_type n) const
7071
  requires random_access_range<Base>
7072
+ { return get-element(current_ + n); }
7073
 
7074
  friend constexpr bool operator==(const iterator& x, const iterator& y)
7075
  requires equality_comparable<iterator_t<Base>>;
7076
 
7077
  friend constexpr bool operator<(const iterator& x, const iterator& y)
7078
  requires random_access_range<Base>;
7079
  friend constexpr bool operator>(const iterator& x, const iterator& y)
7080
  requires random_access_range<Base>;
7081
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
7082
  requires random_access_range<Base>;
7083
  friend constexpr bool operator>=(const iterator& x, const iterator& y)
7084
  requires random_access_range<Base>;
7085
  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
7086
  requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
 
7090
  friend constexpr iterator operator+(difference_type x, const iterator& y)
7091
  requires random_access_range<Base>;
7092
  friend constexpr iterator operator-(const iterator& x, difference_type y)
7093
  requires random_access_range<Base>;
7094
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7095
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
7096
  };
7097
  }
7098
  ```
7099
 
7100
+ The member *typedef-name* `iterator_concept` is defined as follows:
7101
+
7102
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
7103
+ denotes `random_access_iterator_tag`.
7104
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
7105
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
7106
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
7107
+ denotes `forward_iterator_tag`.
7108
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
7109
+
7110
+ The member *typedef-name* `iterator_category` is defined if and only if
7111
+ *`Base`* models `forward_range`. In that case, `iterator_category` is
7112
+ defined as follows: Let `C` denote the type
7113
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
7114
+
7115
+ - If `std::get<N>(*current_)` is an rvalue, `iterator_category` denotes
7116
+ `input_iterator_tag`.
7117
+ - Otherwise, if `C` models `derived_from<random_access_iterator_tag>`,
7118
+ `iterator_category` denotes `random_access_iterator_tag`.
7119
+ - Otherwise, `iterator_category` denotes `C`.
7120
+
7121
+ ``` cpp
7122
+ static constexpr decltype(auto) get-element(const iterator_t<Base>& i);
7123
+ ```
7124
+
7125
+ *Effects:* Equivalent to:
7126
+
7127
+ ``` cpp
7128
+ if constexpr (is_reference_v<range_reference_t<Base>>) {
7129
+ return std::get<N>(*i);
7130
+ } else {
7131
+ using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>;
7132
+ return static_cast<E>(std::get<N>(*i));
7133
+ }
7134
+ ```
7135
+
7136
  ``` cpp
7137
  constexpr explicit iterator(iterator_t<Base> current);
7138
  ```
7139
 
7140
  *Effects:* Initializes *current\_* with `std::move(current)`.
 
7145
  ```
7146
 
7147
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
7148
 
7149
  ``` cpp
7150
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
7151
  ```
7152
 
7153
  *Effects:* Equivalent to: `return `*`current_`*`;`
7154
 
7155
  ``` cpp
 
7168
  ++current_;
7169
  return *this;
7170
  ```
7171
 
7172
  ``` cpp
7173
+ constexpr void operator++(int);
7174
  ```
7175
 
7176
  *Effects:* Equivalent to: `++`*`current_`*.
7177
 
7178
  ``` cpp
 
7209
  --current_;
7210
  return temp;
7211
  ```
7212
 
7213
  ``` cpp
7214
+ constexpr iterator& operator+=(difference_type n)
7215
  requires random_access_range<Base>;
7216
  ```
7217
 
7218
  *Effects:* Equivalent to:
7219
 
 
7280
  ``` cpp
7281
  friend constexpr iterator operator+(const iterator& x, difference_type y)
7282
  requires random_access_range<Base>;
7283
  ```
7284
 
7285
+ *Effects:* Equivalent to: `return `*`iterator`*`{x} += y;`
7286
 
7287
  ``` cpp
7288
  friend constexpr iterator operator+(difference_type x, const iterator& y)
7289
  requires random_access_range<Base>;
7290
  ```
7291
 
7292
  *Effects:* Equivalent to: `return y + x;`
7293
 
7294
  ``` cpp
7295
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
7296
  requires random_access_range<Base>;
7297
  ```
7298
 
7299
+ *Effects:* Equivalent to: `return `*`iterator`*`{x} -= y;`
7300
 
7301
  ``` cpp
7302
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7303
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
7304
  ```
7305
 
7306
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
7307
 
7308
  #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
7309
 
7310
  ``` cpp
7311
  namespace std::ranges {
7312
  template<input_range V, size_t N>
7313
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
7314
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
7315
+ returnable-element<range_reference_t<V>, N>
7316
  template<bool Const>
7317
+ class elements_view<V, N>::sentinel {
7318
  private:
7319
+ using Base = maybe-const<Const, V>; // exposition only
7320
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
7321
+
7322
  public:
7323
  sentinel() = default;
7324
  constexpr explicit sentinel(sentinel_t<Base> end);
7325
  constexpr sentinel(sentinel<!Const> other)
7326
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
7327
 
7328
  constexpr sentinel_t<Base> base() const;
7329
 
7330
+ template<bool OtherConst>
7331
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7332
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
7333
 
7334
+ template<bool OtherConst>
7335
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7336
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7337
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
7338
 
7339
+ template<bool OtherConst>
7340
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7341
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7342
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
7343
  };
7344
  }
7345
  ```
7346
 
7347
  ``` cpp
 
7362
  ```
7363
 
7364
  *Effects:* Equivalent to: `return `*`end_`*`;`
7365
 
7366
  ``` cpp
7367
+ template<bool OtherConst>
7368
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7369
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
7370
  ```
7371
 
7372
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
7373
 
7374
  ``` cpp
7375
+ template<bool OtherConst>
7376
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7377
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7378
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
7379
  ```
7380
 
7381
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
7382
 
7383
  ``` cpp
7384
+ template<bool OtherConst>
7385
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7386
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7387
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
7388
+ ```
7389
+
7390
+ *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
7391
+
7392
+ ### Enumerate view <a id="range.enumerate">[[range.enumerate]]</a>
7393
+
7394
+ #### Overview <a id="range.enumerate.overview">[[range.enumerate.overview]]</a>
7395
+
7396
+ `enumerate_view` is a view whose elements represent both the position
7397
+ and value from a sequence of elements.
7398
+
7399
+ The name `views::enumerate` denotes a range adaptor object. Given a
7400
+ subexpression `E`, the expression `views::enumerate(E)` is
7401
+ expression-equivalent to
7402
+ `enumerate_view<views::all_t<decltype((E))>>(E)`.
7403
+
7404
+ [*Example 1*:
7405
+
7406
+ ``` cpp
7407
+ vector<int> vec{ 1, 2, 3 };
7408
+ for (auto [index, value] : views::enumerate(vec))
7409
+ cout << index << ":" << value << ' '; // prints 0:1 1:2 2:3
7410
+ ```
7411
+
7412
+ — *end example*]
7413
+
7414
+ #### Class template `enumerate_view` <a id="range.enumerate.view">[[range.enumerate.view]]</a>
7415
+
7416
+ ``` cpp
7417
+ namespace std::ranges {
7418
+ template<view V>
7419
+ requires range-with-movable-references<V>
7420
+ class enumerate_view : public view_interface<enumerate_view<V>> {
7421
+ V base_ = V(); // exposition only
7422
+
7423
+ // [range.enumerate.iterator], class template enumerate_view::iterator
7424
+ template<bool Const>
7425
+ class iterator; // exposition only
7426
+
7427
+ // [range.enumerate.sentinel], class template enumerate_view::sentinel
7428
+ template<bool Const>
7429
+ class sentinel; // exposition only
7430
+
7431
+ public:
7432
+ constexpr enumerate_view() requires default_initializable<V> = default;
7433
+ constexpr explicit enumerate_view(V base);
7434
+
7435
+ constexpr auto begin() requires (!simple-view<V>)
7436
+ { return iterator<false>(ranges::begin(base_), 0); }
7437
+ constexpr auto begin() const requires range-with-movable-references<const V>
7438
+ { return iterator<true>(ranges::begin(base_), 0); }
7439
+
7440
+ constexpr auto end() requires (!simple-view<V>) {
7441
+ if constexpr (common_range<V> && sized_range<V>)
7442
+ return iterator<false>(ranges::end(base_), ranges::distance(base_));
7443
+ else
7444
+ return sentinel<false>(ranges::end(base_));
7445
+ }
7446
+ constexpr auto end() const requires range-with-movable-references<const V> {
7447
+ if constexpr (common_range<const V> && sized_range<const V>)
7448
+ return iterator<true>(ranges::end(base_), ranges::distance(base_));
7449
+ else
7450
+ return sentinel<true>(ranges::end(base_));
7451
+ }
7452
+
7453
+ constexpr auto size() requires sized_range<V>
7454
+ { return ranges::size(base_); }
7455
+ constexpr auto size() const requires sized_range<const V>
7456
+ { return ranges::size(base_); }
7457
+
7458
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
7459
+ constexpr V base() && { return std::move(base_); }
7460
+ };
7461
+
7462
+ template<class R>
7463
+ enumerate_view(R&&) -> enumerate_view<views::all_t<R>>;
7464
+ }
7465
+ ```
7466
+
7467
+ ``` cpp
7468
+ constexpr explicit enumerate_view(V base);
7469
+ ```
7470
+
7471
+ *Effects:* Initializes *base\_* with `std::move(base)`.
7472
+
7473
+ #### Class template `enumerate_view::iterator` <a id="range.enumerate.iterator">[[range.enumerate.iterator]]</a>
7474
+
7475
+ ``` cpp
7476
+ namespace std::ranges {
7477
+ template<view V>
7478
+ requires range-with-movable-references<V>
7479
+ template<bool Const>
7480
+ class enumerate_view<V>::iterator {
7481
+ using Base = maybe-const<Const, V>; // exposition only
7482
+
7483
+ public:
7484
+ using iterator_category = input_iterator_tag;
7485
+ using iterator_concept = see below;
7486
+ using difference_type = range_difference_t<Base>;
7487
+ using value_type = tuple<difference_type, range_value_t<Base>>;
7488
+
7489
+ private:
7490
+ using reference-type = // exposition only
7491
+ tuple<difference_type, range_reference_t<Base>>;
7492
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
7493
+ difference_type pos_ = 0; // exposition only
7494
+
7495
+ constexpr explicit
7496
+ iterator(iterator_t<Base> current, difference_type pos); // exposition only
7497
+
7498
+ public:
7499
+ iterator() requires default_initializable<iterator_t<Base>> = default;
7500
+ constexpr iterator(iterator<!Const> i)
7501
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
7502
+
7503
+ constexpr const iterator_t<Base>& base() const & noexcept;
7504
+ constexpr iterator_t<Base> base() &&;
7505
+
7506
+ constexpr difference_type index() const noexcept;
7507
+
7508
+ constexpr auto operator*() const {
7509
+ return reference-type(pos_, *current_);
7510
+ }
7511
+
7512
+ constexpr iterator& operator++();
7513
+ constexpr void operator++(int);
7514
+ constexpr iterator operator++(int) requires forward_range<Base>;
7515
+
7516
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
7517
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
7518
+
7519
+ constexpr iterator& operator+=(difference_type x)
7520
+ requires random_access_range<Base>;
7521
+ constexpr iterator& operator-=(difference_type x)
7522
+ requires random_access_range<Base>;
7523
+
7524
+ constexpr auto operator[](difference_type n) const
7525
+ requires random_access_range<Base>
7526
+ { return reference-type(pos_ + n, current_[n]); }
7527
+
7528
+ friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept;
7529
+ friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept;
7530
+
7531
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
7532
+ requires random_access_range<Base>;
7533
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
7534
+ requires random_access_range<Base>;
7535
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
7536
+ requires random_access_range<Base>;
7537
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y);
7538
+
7539
+ friend constexpr auto iter_move(const iterator& i)
7540
+ noexcept(noexcept(ranges::iter_move(i.current_)) &&
7541
+ is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>) {
7542
+ return tuple<difference_type,
7543
+ range_rvalue_reference_t<Base>>(i.pos_, ranges::iter_move(i.current_));
7544
+ }
7545
+ };
7546
+ }
7547
+ ```
7548
+
7549
+ The member *typedef-name* `iterator::iterator_concept` is defined as
7550
+ follows:
7551
+
7552
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
7553
+ denotes `random_access_iterator_tag`.
7554
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
7555
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
7556
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
7557
+ denotes `forward_iterator_tag`.
7558
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
7559
+
7560
+ ``` cpp
7561
+ constexpr explicit iterator(iterator_t<Base> current, difference_type pos);
7562
+ ```
7563
+
7564
+ *Effects:* Initializes *current\_* with `std::move(current)` and *pos\_*
7565
+ with `pos`.
7566
+
7567
+ ``` cpp
7568
+ constexpr iterator(iterator<!Const> i)
7569
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
7570
+ ```
7571
+
7572
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
7573
+ and *pos\_* with `i.`*`pos_`*.
7574
+
7575
+ ``` cpp
7576
+ constexpr const iterator_t<Base>& base() const & noexcept;
7577
+ ```
7578
+
7579
+ *Effects:* Equivalent to: `return `*`current_`*`;`
7580
+
7581
+ ``` cpp
7582
+ constexpr iterator_t<Base> base() &&;
7583
+ ```
7584
+
7585
+ *Effects:* Equivalent to: `return std::move(`*`current_`*`);`
7586
+
7587
+ ``` cpp
7588
+ constexpr difference_type index() const noexcept;
7589
+ ```
7590
+
7591
+ *Effects:* Equivalent to: `return `*`pos_`*`;`
7592
+
7593
+ ``` cpp
7594
+ constexpr iterator& operator++();
7595
+ ```
7596
+
7597
+ *Effects:* Equivalent to:
7598
+
7599
+ ``` cpp
7600
+ ++current_;
7601
+ ++pos_;
7602
+ return *this;
7603
+ ```
7604
+
7605
+ ``` cpp
7606
+ constexpr void operator++(int);
7607
+ ```
7608
+
7609
+ *Effects:* Equivalent to `++*this`.
7610
+
7611
+ ``` cpp
7612
+ constexpr iterator operator++(int) requires forward_range<Base>;
7613
+ ```
7614
+
7615
+ *Effects:* Equivalent to:
7616
+
7617
+ ``` cpp
7618
+ auto temp = *this;
7619
+ ++*this;
7620
+ return temp;
7621
+ ```
7622
+
7623
+ ``` cpp
7624
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
7625
+ ```
7626
+
7627
+ *Effects:* Equivalent to:
7628
+
7629
+ ``` cpp
7630
+ --current_;
7631
+ --pos_;
7632
+ return *this;
7633
+ ```
7634
+
7635
+ ``` cpp
7636
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
7637
+ ```
7638
+
7639
+ *Effects:* Equivalent to:
7640
+
7641
+ ``` cpp
7642
+ auto temp = *this;
7643
+ --*this;
7644
+ return temp;
7645
+ ```
7646
+
7647
+ ``` cpp
7648
+ constexpr iterator& operator+=(difference_type n)
7649
+ requires random_access_range<Base>;
7650
+ ```
7651
+
7652
+ *Effects:* Equivalent to:
7653
+
7654
+ ``` cpp
7655
+ current_ += n;
7656
+ pos_ += n;
7657
+ return *this;
7658
+ ```
7659
+
7660
+ ``` cpp
7661
+ constexpr iterator& operator-=(difference_type n)
7662
+ requires random_access_range<Base>;
7663
+ ```
7664
+
7665
+ *Effects:* Equivalent to:
7666
+
7667
+ ``` cpp
7668
+ current_ -= n;
7669
+ pos_ -= n;
7670
+ return *this;
7671
+ ```
7672
+
7673
+ ``` cpp
7674
+ friend constexpr bool operator==(const iterator& x, const iterator& y) noexcept;
7675
+ ```
7676
+
7677
+ *Effects:* Equivalent to: `return x.`*`pos_`*` == y.`*`pos_`*`;`
7678
+
7679
+ ``` cpp
7680
+ friend constexpr strong_ordering operator<=>(const iterator& x, const iterator& y) noexcept;
7681
+ ```
7682
+
7683
+ *Effects:* Equivalent to: `return x.`*`pos_`*` <=> y.`*`pos_`*`;`
7684
+
7685
+ ``` cpp
7686
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
7687
+ requires random_access_range<Base>;
7688
+ ```
7689
+
7690
+ *Effects:* Equivalent to:
7691
+
7692
+ ``` cpp
7693
+ auto temp = x;
7694
+ temp += y;
7695
+ return temp;
7696
+ ```
7697
+
7698
+ ``` cpp
7699
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
7700
+ requires random_access_range<Base>;
7701
+ ```
7702
+
7703
+ *Effects:* Equivalent to: `return y + x;`
7704
+
7705
+ ``` cpp
7706
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
7707
+ requires random_access_range<Base>;
7708
+ ```
7709
+
7710
+ *Effects:* Equivalent to:
7711
+
7712
+ ``` cpp
7713
+ auto temp = x;
7714
+ temp -= y;
7715
+ return temp;
7716
+ ```
7717
+
7718
+ ``` cpp
7719
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y);
7720
+ ```
7721
+
7722
+ *Effects:* Equivalent to: `return x.`*`pos_`*` - y.`*`pos_`*`;`
7723
+
7724
+ #### Class template `enumerate_view::sentinel` <a id="range.enumerate.sentinel">[[range.enumerate.sentinel]]</a>
7725
+
7726
+ ``` cpp
7727
+ namespace std::ranges {
7728
+ template<view V>
7729
+ requires range-with-movable-references<V>
7730
+ template<bool Const>
7731
+ class enumerate_view<V>::sentinel {
7732
+ using Base = maybe-const<Const, V>; // exposition only
7733
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
7734
+ constexpr explicit sentinel(sentinel_t<Base> end); // exposition only
7735
+
7736
+ public:
7737
+ sentinel() = default;
7738
+ constexpr sentinel(sentinel<!Const> other)
7739
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
7740
+
7741
+ constexpr sentinel_t<Base> base() const;
7742
+
7743
+ template<bool OtherConst>
7744
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7745
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
7746
+
7747
+ template<bool OtherConst>
7748
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7749
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7750
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
7751
+
7752
+ template<bool OtherConst>
7753
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7754
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7755
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
7756
+ };
7757
+ }
7758
+ ```
7759
+
7760
+ ``` cpp
7761
+ constexpr explicit sentinel(sentinel_t<Base> end);
7762
+ ```
7763
+
7764
+ *Effects:* Initializes *end\_* with `std::move(end)`.
7765
+
7766
+ ``` cpp
7767
+ constexpr sentinel(sentinel<!Const> other)
7768
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
7769
+ ```
7770
+
7771
+ *Effects:* Initializes *end\_* with `std::move(other.`*`end_`*`)`.
7772
+
7773
+ ``` cpp
7774
+ constexpr sentinel_t<Base> base() const;
7775
+ ```
7776
+
7777
+ *Effects:* Equivalent to: `return `*`end_`*`;`
7778
+
7779
+ ``` cpp
7780
+ template<bool OtherConst>
7781
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7782
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
7783
+ ```
7784
+
7785
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
7786
+
7787
+ ``` cpp
7788
+ template<bool OtherConst>
7789
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7790
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7791
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
7792
+ ```
7793
+
7794
+ *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
7795
+
7796
+ ``` cpp
7797
+ template<bool OtherConst>
7798
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
7799
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
7800
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
7801
  ```
7802
 
7803
  *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
7804
 
7805
+ ### Zip view <a id="range.zip">[[range.zip]]</a>
7806
+
7807
+ #### Overview <a id="range.zip.overview">[[range.zip.overview]]</a>
7808
+
7809
+ `zip_view` takes any number of views and produces a view of tuples of
7810
+ references to the corresponding elements of the constituent views.
7811
+
7812
+ The name `views::zip` denotes a customization point object
7813
+ [[customization.point.object]]. Given a pack of subexpressions `Es...`,
7814
+ the expression `views::zip(Es...)` is expression-equivalent to
7815
+
7816
+ - `auto(views::empty<tuple<>>)` if `Es` is an empty pack,
7817
+ - otherwise, `zip_view<views::all_t<decltype((Es))>...>(Es...)`.
7818
+
7819
+ [*Example 1*:
7820
+
7821
+ ``` cpp
7822
+ vector v = {1, 2};
7823
+ list l = {'a', 'b', 'c'};
7824
+
7825
+ auto z = views::zip(v, l);
7826
+ range_reference_t<decltype(z)> f = z.front(); // f is a tuple<int&, char&>
7827
+ // that refers to the first element of v and l
7828
+
7829
+ for (auto&& [x, y] : z) {
7830
+ cout << '(' << x << ", " << y << ") "; // prints (1, a) (2, b)
7831
+ }
7832
+ ```
7833
+
7834
+ — *end example*]
7835
+
7836
+ #### Class template `zip_view` <a id="range.zip.view">[[range.zip.view]]</a>
7837
+
7838
+ ``` cpp
7839
+ namespace std::ranges {
7840
+ template<class... Rs>
7841
+ concept zip-is-common = // exposition only
7842
+ (sizeof...(Rs) == 1 && (common_range<Rs> && ...)) ||
7843
+ (!(bidirectional_range<Rs> && ...) && (common_range<Rs> && ...)) ||
7844
+ ((random_access_range<Rs> && ...) && (sized_range<Rs> && ...));
7845
+
7846
+ template<input_range... Views>
7847
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
7848
+ class zip_view : public view_interface<zip_view<Views...>> {
7849
+ tuple<Views...> views_; // exposition only
7850
+
7851
+ // [range.zip.iterator], class template zip_view::iterator
7852
+ template<bool> class iterator; // exposition only
7853
+
7854
+ // [range.zip.sentinel], class template zip_view::sentinel
7855
+ template<bool> class sentinel; // exposition only
7856
+
7857
+ public:
7858
+ zip_view() = default;
7859
+ constexpr explicit zip_view(Views... views);
7860
+
7861
+ constexpr auto begin() requires (!(simple-view<Views> && ...)) {
7862
+ return iterator<false>(tuple-transform(ranges::begin, views_));
7863
+ }
7864
+ constexpr auto begin() const requires (range<const Views> && ...) {
7865
+ return iterator<true>(tuple-transform(ranges::begin, views_));
7866
+ }
7867
+
7868
+ constexpr auto end() requires (!(simple-view<Views> && ...)) {
7869
+ if constexpr (!zip-is-common<Views...>) {
7870
+ return sentinel<false>(tuple-transform(ranges::end, views_));
7871
+ } else if constexpr ((random_access_range<Views> && ...)) {
7872
+ return begin() + iter_difference_t<iterator<false>>(size());
7873
+ } else {
7874
+ return iterator<false>(tuple-transform(ranges::end, views_));
7875
+ }
7876
+ }
7877
+
7878
+ constexpr auto end() const requires (range<const Views> && ...) {
7879
+ if constexpr (!zip-is-common<const Views...>) {
7880
+ return sentinel<true>(tuple-transform(ranges::end, views_));
7881
+ } else if constexpr ((random_access_range<const Views> && ...)) {
7882
+ return begin() + iter_difference_t<iterator<true>>(size());
7883
+ } else {
7884
+ return iterator<true>(tuple-transform(ranges::end, views_));
7885
+ }
7886
+ }
7887
+
7888
+ constexpr auto size() requires (sized_range<Views> && ...);
7889
+ constexpr auto size() const requires (sized_range<const Views> && ...);
7890
+ };
7891
+
7892
+ template<class... Rs>
7893
+ zip_view(Rs&&...) -> zip_view<views::all_t<Rs>...>;
7894
+ }
7895
+ ```
7896
+
7897
+ Two `zip_view` objects have the same underlying sequence if and only if
7898
+ the corresponding elements of *`views_`* are equal [[concepts.equality]]
7899
+ and have the same underlying sequence.
7900
+
7901
+ [*Note 1*: In particular, comparison of iterators obtained from
7902
+ `zip_view` objects that do not have the same underlying sequence is not
7903
+ required to produce meaningful results
7904
+ [[iterator.concept.forward]]. — *end note*]
7905
+
7906
+ ``` cpp
7907
+ constexpr explicit zip_view(Views... views);
7908
+ ```
7909
+
7910
+ *Effects:* Initializes *views\_* with `std::move(views)...`.
7911
+
7912
+ ``` cpp
7913
+ constexpr auto size() requires (sized_range<Views> && ...);
7914
+ constexpr auto size() const requires (sized_range<const Views> && ...);
7915
+ ```
7916
+
7917
+ *Effects:* Equivalent to:
7918
+
7919
+ ``` cpp
7920
+ return apply([](auto... sizes) {
7921
+ using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>;
7922
+ return ranges::min({CT(sizes)...});
7923
+ }, tuple-transform(ranges::size, views_));
7924
+ ```
7925
+
7926
+ #### Class template `zip_view::iterator` <a id="range.zip.iterator">[[range.zip.iterator]]</a>
7927
+
7928
+ ``` cpp
7929
+ namespace std::ranges {
7930
+ template<bool Const, class... Views>
7931
+ concept all-random-access = // exposition only
7932
+ (random_access_range<maybe-const<Const, Views>> && ...);
7933
+ template<bool Const, class... Views>
7934
+ concept all-bidirectional = // exposition only
7935
+ (bidirectional_range<maybe-const<Const, Views>> && ...);
7936
+ template<bool Const, class... Views>
7937
+ concept all-forward = // exposition only
7938
+ (forward_range<maybe-const<Const, Views>> && ...);
7939
+
7940
+ template<input_range... Views>
7941
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
7942
+ template<bool Const>
7943
+ class zip_view<Views...>::iterator {
7944
+ tuple<iterator_t<maybe-const<Const, Views>>...> current_; // exposition only
7945
+ constexpr explicit iterator(tuple<iterator_t<maybe-const<Const, Views>>...>);
7946
+ // exposition only
7947
+ public:
7948
+ using iterator_category = input_iterator_tag; // not always present
7949
+ using iterator_concept = see below;
7950
+ using value_type = tuple<range_value_t<maybe-const<Const, Views>>...>;
7951
+ using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>;
7952
+
7953
+ iterator() = default;
7954
+ constexpr iterator(iterator<!Const> i)
7955
+ requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
7956
+
7957
+ constexpr auto operator*() const;
7958
+ constexpr iterator& operator++();
7959
+ constexpr void operator++(int);
7960
+ constexpr iterator operator++(int) requires all-forward<Const, Views...>;
7961
+
7962
+ constexpr iterator& operator--() requires all-bidirectional<Const, Views...>;
7963
+ constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>;
7964
+
7965
+ constexpr iterator& operator+=(difference_type x)
7966
+ requires all-random-access<Const, Views...>;
7967
+ constexpr iterator& operator-=(difference_type x)
7968
+ requires all-random-access<Const, Views...>;
7969
+
7970
+ constexpr auto operator[](difference_type n) const
7971
+ requires all-random-access<Const, Views...>;
7972
+
7973
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
7974
+ requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
7975
+
7976
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
7977
+ requires all-random-access<Const, Views...>;
7978
+
7979
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
7980
+ requires all-random-access<Const, Views...>;
7981
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
7982
+ requires all-random-access<Const, Views...>;
7983
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
7984
+ requires all-random-access<Const, Views...>;
7985
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
7986
+ requires (sized_sentinel_for<iterator_t<maybe-const<Const, Views>>,
7987
+ iterator_t<maybe-const<Const, Views>>> && ...);
7988
+
7989
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
7990
+
7991
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
7992
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...);
7993
+ };
7994
+ }
7995
+ ```
7996
+
7997
+ `iterator::iterator_concept` is defined as follows:
7998
+
7999
+ - If `all-random-access<Const, Views...>` is modeled, then
8000
+ `iterator_concept` denotes `random_access_iterator_tag`.
8001
+ - Otherwise, if `all-bidirectional<Const, Views...>` is modeled, then
8002
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
8003
+ - Otherwise, if `all-forward<Const, Views...>` is modeled, then
8004
+ `iterator_concept` denotes `forward_iterator_tag`.
8005
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
8006
+
8007
+ `iterator::iterator_category` is present if and only if
8008
+ `all-forward<Const, Views...>` is modeled.
8009
+
8010
+ If the invocation of any non-const member function of *`iterator`* exits
8011
+ via an exception, the iterator acquires a singular value.
8012
+
8013
+ ``` cpp
8014
+ constexpr explicit iterator(tuple<iterator_t<maybe-const<Const, Views>>...> current);
8015
+ ```
8016
+
8017
+ *Effects:* Initializes *current\_* with `std::move(current)`.
8018
+
8019
+ ``` cpp
8020
+ constexpr iterator(iterator<!Const> i)
8021
+ requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
8022
+ ```
8023
+
8024
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
8025
+
8026
+ ``` cpp
8027
+ constexpr auto operator*() const;
8028
+ ```
8029
+
8030
+ *Effects:* Equivalent to:
8031
+
8032
+ ``` cpp
8033
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
8034
+ ```
8035
+
8036
+ ``` cpp
8037
+ constexpr iterator& operator++();
8038
+ ```
8039
+
8040
+ *Effects:* Equivalent to:
8041
+
8042
+ ``` cpp
8043
+ tuple-for-each([](auto& i) { ++i; }, current_);
8044
+ return *this;
8045
+ ```
8046
+
8047
+ ``` cpp
8048
+ constexpr void operator++(int);
8049
+ ```
8050
+
8051
+ *Effects:* Equivalent to `++*this`.
8052
+
8053
+ ``` cpp
8054
+ constexpr iterator operator++(int) requires all-forward<Const, Views...>;
8055
+ ```
8056
+
8057
+ *Effects:* Equivalent to:
8058
+
8059
+ ``` cpp
8060
+ auto tmp = *this;
8061
+ ++*this;
8062
+ return tmp;
8063
+ ```
8064
+
8065
+ ``` cpp
8066
+ constexpr iterator& operator--() requires all-bidirectional<Const, Views...>;
8067
+ ```
8068
+
8069
+ *Effects:* Equivalent to:
8070
+
8071
+ ``` cpp
8072
+ tuple-for-each([](auto& i) { --i; }, current_);
8073
+ return *this;
8074
+ ```
8075
+
8076
+ ``` cpp
8077
+ constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>;
8078
+ ```
8079
+
8080
+ *Effects:* Equivalent to:
8081
+
8082
+ ``` cpp
8083
+ auto tmp = *this;
8084
+ --*this;
8085
+ return tmp;
8086
+ ```
8087
+
8088
+ ``` cpp
8089
+ constexpr iterator& operator+=(difference_type x)
8090
+ requires all-random-access<Const, Views...>;
8091
+ ```
8092
+
8093
+ *Effects:* Equivalent to:
8094
+
8095
+ ``` cpp
8096
+ tuple-for-each([&]<class I>(I& i) { i += iter_difference_t<I>(x); }, current_);
8097
+ return *this;
8098
+ ```
8099
+
8100
+ ``` cpp
8101
+ constexpr iterator& operator-=(difference_type x)
8102
+ requires all-random-access<Const, Views...>;
8103
+ ```
8104
+
8105
+ *Effects:* Equivalent to:
8106
+
8107
+ ``` cpp
8108
+ tuple-for-each([&]<class I>(I& i) { i -= iter_difference_t<I>(x); }, current_);
8109
+ return *this;
8110
+ ```
8111
+
8112
+ ``` cpp
8113
+ constexpr auto operator[](difference_type n) const
8114
+ requires all-random-access<Const, Views...>;
8115
+ ```
8116
+
8117
+ *Effects:* Equivalent to:
8118
+
8119
+ ``` cpp
8120
+ return tuple-transform([&]<class I>(I& i) -> decltype(auto) {
8121
+ return i[iter_difference_t<I>(n)];
8122
+ }, current_);
8123
+ ```
8124
+
8125
+ ``` cpp
8126
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
8127
+ requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
8128
+ ```
8129
+
8130
+ *Returns:*
8131
+
8132
+ - `x.`*`current_`*` == y.`*`current_`* if
8133
+ `all-bidirectional<Const, Views...>` is `true`.
8134
+ - Otherwise, `true` if there exists an integer
8135
+ 0 ≤ i < `sizeof...(Views)` such that
8136
+ `bool(std::get<`i`>(x.`*`current_`*`) == std::get<`i`>(y.`*`current_`*`))`
8137
+ is `true`. \[*Note 1*: This allows `zip_view` to model `common_range`
8138
+ when all constituent views model `common_range`. — *end note*]
8139
+ - Otherwise, `false`.
8140
+
8141
+ ``` cpp
8142
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8143
+ requires all-random-access<Const, Views...>;
8144
+ ```
8145
+
8146
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
8147
+
8148
+ ``` cpp
8149
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
8150
+ requires all-random-access<Const, Views...>;
8151
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
8152
+ requires all-random-access<Const, Views...>;
8153
+ ```
8154
+
8155
+ *Effects:* Equivalent to:
8156
+
8157
+ ``` cpp
8158
+ auto r = i;
8159
+ r += n;
8160
+ return r;
8161
+ ```
8162
+
8163
+ ``` cpp
8164
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
8165
+ requires all-random-access<Const, Views...>;
8166
+ ```
8167
+
8168
+ *Effects:* Equivalent to:
8169
+
8170
+ ``` cpp
8171
+ auto r = i;
8172
+ r -= n;
8173
+ return r;
8174
+ ```
8175
+
8176
+ ``` cpp
8177
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8178
+ requires (sized_sentinel_for<iterator_t<maybe-const<Const, Views>>,
8179
+ iterator_t<maybe-const<Const, Views>>> && ...);
8180
+ ```
8181
+
8182
+ Let *`DIST`*`(`i`)` be
8183
+ `difference_type(std::get<`i`>(x.`*`current_`*`) - std::get<`i`>(y.`*`current_`*`))`.
8184
+
8185
+ *Returns:* The value with the smallest absolute value among
8186
+ *`DIST`*`(`n`)` for all integers 0 ≤ n < `sizeof...(Views)`.
8187
+
8188
+ ``` cpp
8189
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
8190
+ ```
8191
+
8192
+ *Effects:* Equivalent to:
8193
+
8194
+ ``` cpp
8195
+ return tuple-transform(ranges::iter_move, i.current_);
8196
+ ```
8197
+
8198
+ *Remarks:* The exception specification is equivalent to:
8199
+
8200
+ ``` cpp
8201
+ (noexcept(ranges::iter_move(declval<const iterator_t<maybe-const<Const,
8202
+ Views>>&>())) && ...) &&
8203
+ (is_nothrow_move_constructible_v<range_rvalue_reference_t<maybe-const<Const,
8204
+ Views>>> && ...)
8205
+ ```
8206
+
8207
+ ``` cpp
8208
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
8209
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...);
8210
+ ```
8211
+
8212
+ *Effects:* For every integer 0 ≤ i < `sizeof...(Views)`, performs:
8213
+
8214
+ ``` cpp
8215
+ ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
8216
+ ```
8217
+
8218
+ *Remarks:* The exception specification is equivalent to the logical of
8219
+ the following expressions:
8220
+
8221
+ ``` cpp
8222
+ noexcept(ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_)))
8223
+ ```
8224
+
8225
+ for every integer 0 ≤ i < `sizeof...(Views)`.
8226
+
8227
+ #### Class template `zip_view::sentinel` <a id="range.zip.sentinel">[[range.zip.sentinel]]</a>
8228
+
8229
+ ``` cpp
8230
+ namespace std::ranges {
8231
+ template<input_range... Views>
8232
+ requires (view<Views> && ...) && (sizeof...(Views) > 0)
8233
+ template<bool Const>
8234
+ class zip_view<Views...>::sentinel {
8235
+ tuple<sentinel_t<maybe-const<Const, Views>>...> end_; // exposition only
8236
+ constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> end);
8237
+ // exposition only
8238
+ public:
8239
+ sentinel() = default;
8240
+ constexpr sentinel(sentinel<!Const> i)
8241
+ requires Const && (convertible_to<sentinel_t<Views>, sentinel_t<const Views>> && ...);
8242
+
8243
+ template<bool OtherConst>
8244
+ requires (sentinel_for<sentinel_t<maybe-const<Const, Views>>,
8245
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
8246
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
8247
+
8248
+ template<bool OtherConst>
8249
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
8250
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
8251
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
8252
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
8253
+
8254
+ template<bool OtherConst>
8255
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
8256
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
8257
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
8258
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
8259
+ };
8260
+ }
8261
+ ```
8262
+
8263
+ ``` cpp
8264
+ constexpr explicit sentinel(tuple<sentinel_t<maybe-const<Const, Views>>...> end);
8265
+ ```
8266
+
8267
+ *Effects:* Initializes *end\_* with `end`.
8268
+
8269
+ ``` cpp
8270
+ constexpr sentinel(sentinel<!Const> i)
8271
+ requires Const && (convertible_to<sentinel_t<Views>, sentinel_t<const Views>> && ...);
8272
+ ```
8273
+
8274
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
8275
+
8276
+ ``` cpp
8277
+ template<bool OtherConst>
8278
+ requires (sentinel_for<sentinel_t<maybe-const<Const, Views>>,
8279
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
8280
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
8281
+ ```
8282
+
8283
+ *Returns:* `true` if there exists an integer 0 ≤ i < `sizeof...(Views)`
8284
+ such that
8285
+ `bool(std::get<`i`>(x.`*`current_`*`) == std::get<`i`>(y.`*`end_`*`))`
8286
+ is `true`. Otherwise, `false`.
8287
+
8288
+ ``` cpp
8289
+ template<bool OtherConst>
8290
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
8291
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
8292
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
8293
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
8294
+ ```
8295
+
8296
+ Let `D` be the return type. Let *`DIST`*`(`i`)` be
8297
+ `D(std::get<`i`>(x.`*`current_`*`) - std::get<`i`>(y.`*`end_`*`))`.
8298
+
8299
+ *Returns:* The value with the smallest absolute value among
8300
+ *`DIST`*`(`n`)` for all integers 0 ≤ n < `sizeof...(Views)`.
8301
+
8302
+ ``` cpp
8303
+ template<bool OtherConst>
8304
+ requires (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
8305
+ iterator_t<maybe-const<OtherConst, Views>>> && ...)
8306
+ friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
8307
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
8308
+ ```
8309
+
8310
+ *Effects:* Equivalent to `return -(x - y);`
8311
+
8312
+ ### Zip transform view <a id="range.zip.transform">[[range.zip.transform]]</a>
8313
+
8314
+ #### Overview <a id="range.zip.transform.overview">[[range.zip.transform.overview]]</a>
8315
+
8316
+ `zip_transform_view` takes an invocable object and any number of views
8317
+ and produces a view whose Mᵗʰ element is the result of applying the
8318
+ invocable object to the Mᵗʰ elements of all views.
8319
+
8320
+ The name `views::zip_transform` denotes a customization point object
8321
+ [[customization.point.object]]. Let `F` be a subexpression, and let
8322
+ `Es...` be a pack of subexpressions.
8323
+
8324
+ - If `Es` is an empty pack, let `FD` be `decay_t<decltype((F))>`.
8325
+ - If `move_constructible<FD> &&
8326
+ regular_invocable<FD&>` is `false`, or if
8327
+ `decay_t<invoke_result_t<FD&>>` is not an object type,
8328
+ `views::zip_transform(F, Es...)` is ill-formed.
8329
+ - Otherwise, the expression `views::zip_transform(F, Es...)` is
8330
+ expression-equivalent to
8331
+ ``` cpp
8332
+ ((void)F, auto(views::empty<decay_t<invoke_result_t<FD&>>>))
8333
+ ```
8334
+ - Otherwise, the expression `views::zip_transform(F, Es...)` is
8335
+ expression-equivalent to `zip_transform_view(F, Es...)`.
8336
+
8337
+ [*Example 1*:
8338
+
8339
+ ``` cpp
8340
+ vector v1 = {1, 2};
8341
+ vector v2 = {4, 5, 6};
8342
+
8343
+ for (auto i : views::zip_transform(plus(), v1, v2)) {
8344
+ cout << i << ' '; // prints 5 7
8345
+ }
8346
+ ```
8347
+
8348
+ — *end example*]
8349
+
8350
+ #### Class template `zip_transform_view` <a id="range.zip.transform.view">[[range.zip.transform.view]]</a>
8351
+
8352
+ ``` cpp
8353
+ namespace std::ranges {
8354
+ template<move_constructible F, input_range... Views>
8355
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
8356
+ regular_invocable<F&, range_reference_t<Views>...> &&
8357
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
8358
+ class zip_transform_view : public view_interface<zip_transform_view<F, Views...>> {
8359
+ movable-box<F> fun_; // exposition only
8360
+ zip_view<Views...> zip_; // exposition only
8361
+
8362
+ using InnerView = zip_view<Views...>; // exposition only
8363
+ template<bool Const>
8364
+ using ziperator = iterator_t<maybe-const<Const, InnerView>>; // exposition only
8365
+ template<bool Const>
8366
+ using zentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only
8367
+
8368
+ // [range.zip.transform.iterator], class template zip_transform_view::iterator
8369
+ template<bool> class iterator; // exposition only
8370
+
8371
+ // [range.zip.transform.sentinel], class template zip_transform_view::sentinel
8372
+ template<bool> class sentinel; // exposition only
8373
+
8374
+ public:
8375
+ zip_transform_view() = default;
8376
+
8377
+ constexpr explicit zip_transform_view(F fun, Views... views);
8378
+
8379
+ constexpr auto begin() { return iterator<false>(*this, zip_.begin()); }
8380
+
8381
+ constexpr auto begin() const
8382
+ requires range<const InnerView> &&
8383
+ regular_invocable<const F&, range_reference_t<const Views>...> {
8384
+ return iterator<true>(*this, zip_.begin());
8385
+ }
8386
+
8387
+ constexpr auto end() {
8388
+ if constexpr (common_range<InnerView>) {
8389
+ return iterator<false>(*this, zip_.end());
8390
+ } else {
8391
+ return sentinel<false>(zip_.end());
8392
+ }
8393
+ }
8394
+
8395
+ constexpr auto end() const
8396
+ requires range<const InnerView> &&
8397
+ regular_invocable<const F&, range_reference_t<const Views>...> {
8398
+ if constexpr (common_range<const InnerView>) {
8399
+ return iterator<true>(*this, zip_.end());
8400
+ } else {
8401
+ return sentinel<true>(zip_.end());
8402
+ }
8403
+ }
8404
+
8405
+ constexpr auto size() requires sized_range<InnerView> {
8406
+ return zip_.size();
8407
+ }
8408
+
8409
+ constexpr auto size() const requires sized_range<const InnerView> {
8410
+ return zip_.size();
8411
+ }
8412
+ };
8413
+
8414
+ template<class F, class... Rs>
8415
+ zip_transform_view(F, Rs&&...) -> zip_transform_view<F, views::all_t<Rs>...>;
8416
+ }
8417
+ ```
8418
+
8419
+ ``` cpp
8420
+ constexpr explicit zip_transform_view(F fun, Views... views);
8421
+ ```
8422
+
8423
+ *Effects:* Initializes *fun\_* with `std::move(fun)` and *zip\_* with
8424
+ `std::move(views)...`.
8425
+
8426
+ #### Class template `zip_transform_view::iterator` <a id="range.zip.transform.iterator">[[range.zip.transform.iterator]]</a>
8427
+
8428
+ ``` cpp
8429
+ namespace std::ranges {
8430
+ template<move_constructible F, input_range... Views>
8431
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
8432
+ regular_invocable<F&, range_reference_t<Views>...> &&
8433
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
8434
+ template<bool Const>
8435
+ class zip_transform_view<F, Views...>::iterator {
8436
+ using Parent = maybe-const<Const, zip_transform_view>; // exposition only
8437
+ using Base = maybe-const<Const, InnerView>; // exposition only
8438
+ Parent* parent_ = nullptr; // exposition only
8439
+ ziperator<Const> inner_; // exposition only
8440
+
8441
+ constexpr iterator(Parent& parent, ziperator<Const> inner); // exposition only
8442
+
8443
+ public:
8444
+ using iterator_category = see belownc; // not always present
8445
+ using iterator_concept = typename ziperator<Const>::iterator_concept;
8446
+ using value_type =
8447
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
8448
+ range_reference_t<maybe-const<Const, Views>>...>>;
8449
+ using difference_type = range_difference_t<Base>;
8450
+
8451
+ iterator() = default;
8452
+ constexpr iterator(iterator<!Const> i)
8453
+ requires Const && convertible_to<ziperator<false>, ziperator<Const>>;
8454
+
8455
+ constexpr decltype(auto) operator*() const noexcept(see below);
8456
+ constexpr iterator& operator++();
8457
+ constexpr void operator++(int);
8458
+ constexpr iterator operator++(int) requires forward_range<Base>;
8459
+
8460
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
8461
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
8462
+
8463
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
8464
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
8465
+
8466
+ constexpr decltype(auto) operator[](difference_type n) const
8467
+ requires random_access_range<Base>;
8468
+
8469
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
8470
+ requires equality_comparable<ziperator<Const>>;
8471
+
8472
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8473
+ requires random_access_range<Base>;
8474
+
8475
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
8476
+ requires random_access_range<Base>;
8477
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
8478
+ requires random_access_range<Base>;
8479
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
8480
+ requires random_access_range<Base>;
8481
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8482
+ requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>;
8483
+ };
8484
+ }
8485
+ ```
8486
+
8487
+ The member *typedef-name* `iterator::iterator_category` is defined if
8488
+ and only if *`Base`* models `forward_range`. In that case,
8489
+ `iterator::iterator_category` is defined as follows:
8490
+
8491
+ - If
8492
+ ``` cpp
8493
+ invoke_result_t<maybe-const<Const, F>&, range_reference_t<maybe-const<Const, Views>>...>
8494
+ ```
8495
+
8496
+ is not a reference, `iterator_category` denotes `input_iterator_tag`.
8497
+ - Otherwise, let `Cs` denote the pack of types
8498
+ `iterator_traits<iterator_t<maybe-const<Const, Views>>>::iterator_category...`.
8499
+ - If `(derived_from<Cs, random_access_iterator_tag> && ...)` is
8500
+ `true`, `iterator_category` denotes `random_access_iterator_tag`.
8501
+ - Otherwise, if
8502
+ `(derived_from<Cs, bidirectional_iterator_tag> && ...)` is `true`,
8503
+ `iterator_category` denotes `bidirectional_iterator_tag`.
8504
+ - Otherwise, if `(derived_from<Cs, forward_iterator_tag> && ...)` is
8505
+ `true`, `iterator_category` denotes `forward_iterator_tag`.
8506
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
8507
+
8508
+ ``` cpp
8509
+ constexpr iterator(Parent& parent, ziperator<Const> inner);
8510
+ ```
8511
+
8512
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and *inner\_*
8513
+ with `std::move(inner)`.
8514
+
8515
+ ``` cpp
8516
+ constexpr iterator(iterator<!Const> i)
8517
+ requires Const && convertible_to<ziperator<false>, ziperator<Const>>;
8518
+ ```
8519
+
8520
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *inner\_*
8521
+ with `std::move(i.`*`inner_`*`)`.
8522
+
8523
+ ``` cpp
8524
+ constexpr decltype(auto) operator*() const noexcept(see below);
8525
+ ```
8526
+
8527
+ *Effects:* Equivalent to:
8528
+
8529
+ ``` cpp
8530
+ return apply([&](const auto&... iters) -> decltype(auto) {
8531
+ return invoke(*parent_->fun_, *iters...);
8532
+ }, inner_.current_);
8533
+ ```
8534
+
8535
+ *Remarks:* Let `Is` be the pack `0, 1, …, ``(sizeof...(Views)-1)`. The
8536
+ exception specification is equivalent to:
8537
+ `noexcept(invoke(*`*`parent_`*`->`*`fun_`*`, *std::get<Is>(`*`inner_`*`.`*`current_`*`)...))`.
8538
+
8539
+ ``` cpp
8540
+ constexpr iterator& operator++();
8541
+ ```
8542
+
8543
+ *Effects:* Equivalent to:
8544
+
8545
+ ``` cpp
8546
+ ++inner_;
8547
+ return *this;
8548
+ ```
8549
+
8550
+ ``` cpp
8551
+ constexpr void operator++(int);
8552
+ ```
8553
+
8554
+ *Effects:* Equivalent to: `++*this`.
8555
+
8556
+ ``` cpp
8557
+ constexpr iterator operator++(int) requires forward_range<Base>;
8558
+ ```
8559
+
8560
+ *Effects:* Equivalent to:
8561
+
8562
+ ``` cpp
8563
+ auto tmp = *this;
8564
+ ++*this;
8565
+ return tmp;
8566
+ ```
8567
+
8568
+ ``` cpp
8569
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
8570
+ ```
8571
+
8572
+ *Effects:* Equivalent to:
8573
+
8574
+ ``` cpp
8575
+ --inner_;
8576
+ return *this;
8577
+ ```
8578
+
8579
+ ``` cpp
8580
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
8581
+ ```
8582
+
8583
+ *Effects:* Equivalent to:
8584
+
8585
+ ``` cpp
8586
+ auto tmp = *this;
8587
+ --*this;
8588
+ return tmp;
8589
+ ```
8590
+
8591
+ ``` cpp
8592
+ constexpr iterator& operator+=(difference_type x)
8593
+ requires random_access_range<Base>;
8594
+ ```
8595
+
8596
+ *Effects:* Equivalent to:
8597
+
8598
+ ``` cpp
8599
+ inner_ += x;
8600
+ return *this;
8601
+ ```
8602
+
8603
+ ``` cpp
8604
+ constexpr iterator& operator-=(difference_type x)
8605
+ requires random_access_range<Base>;
8606
+ ```
8607
+
8608
+ *Effects:* Equivalent to:
8609
+
8610
+ ``` cpp
8611
+ inner_ -= x;
8612
+ return *this;
8613
+ ```
8614
+
8615
+ ``` cpp
8616
+ constexpr decltype(auto) operator[](difference_type n) const
8617
+ requires random_access_range<Base>;
8618
+ ```
8619
+
8620
+ *Effects:* Equivalent to:
8621
+
8622
+ ``` cpp
8623
+ return apply([&]<class... Is>(const Is&... iters) -> decltype(auto) {
8624
+ return invoke(*parent_->fun_, iters[iter_difference_t<Is>(n)]...);
8625
+ }, inner_.current_);
8626
+ ```
8627
+
8628
+ ``` cpp
8629
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
8630
+ requires equality_comparable<ziperator<Const>>;
8631
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8632
+ requires random_access_range<Base>;
8633
+ ```
8634
+
8635
+ Let *op* be the operator.
8636
+
8637
+ *Effects:* Equivalent to:
8638
+ `return x.`*`inner_`*` `*`op`*` y.`*`inner_`*`;`
8639
+
8640
+ ``` cpp
8641
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
8642
+ requires random_access_range<Base>;
8643
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
8644
+ requires random_access_range<Base>;
8645
+ ```
8646
+
8647
+ *Effects:* Equivalent to:
8648
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` + n);`
8649
+
8650
+ ``` cpp
8651
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
8652
+ requires random_access_range<Base>;
8653
+ ```
8654
+
8655
+ *Effects:* Equivalent to:
8656
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` - n);`
8657
+
8658
+ ``` cpp
8659
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8660
+ requires sized_sentinel_for<ziperator<Const>, ziperator<Const>>;
8661
+ ```
8662
+
8663
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
8664
+
8665
+ #### Class template `zip_transform_view::sentinel` <a id="range.zip.transform.sentinel">[[range.zip.transform.sentinel]]</a>
8666
+
8667
+ ``` cpp
8668
+ namespace std::ranges {
8669
+ template<move_constructible F, input_range... Views>
8670
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) && is_object_v<F> &&
8671
+ regular_invocable<F&, range_reference_t<Views>...> &&
8672
+ can-reference<invoke_result_t<F&, range_reference_t<Views>...>>
8673
+ template<bool Const>
8674
+ class zip_transform_view<F, Views...>::sentinel {
8675
+ zentinel<Const> inner_; // exposition only
8676
+ constexpr explicit sentinel(zentinel<Const> inner); // exposition only
8677
+
8678
+ public:
8679
+ sentinel() = default;
8680
+ constexpr sentinel(sentinel<!Const> i)
8681
+ requires Const && convertible_to<zentinel<false>, zentinel<Const>>;
8682
+
8683
+ template<bool OtherConst>
8684
+ requires sentinel_for<zentinel<Const>, ziperator<OtherConst>>
8685
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
8686
+
8687
+ template<bool OtherConst>
8688
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
8689
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
8690
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
8691
+
8692
+ template<bool OtherConst>
8693
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
8694
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
8695
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
8696
+ };
8697
+ }
8698
+ ```
8699
+
8700
+ ``` cpp
8701
+ constexpr explicit sentinel(zentinel<Const> inner);
8702
+ ```
8703
+
8704
+ *Effects:* Initializes *inner\_* with `inner`.
8705
+
8706
+ ``` cpp
8707
+ constexpr sentinel(sentinel<!Const> i)
8708
+ requires Const && convertible_to<zentinel<false>, zentinel<Const>>;
8709
+ ```
8710
+
8711
+ *Effects:* Initializes *inner\_* with `std::move(i.`*`inner_`*`)`.
8712
+
8713
+ ``` cpp
8714
+ template<bool OtherConst>
8715
+ requires sentinel_for<zentinel<Const>, ziperator<OtherConst>>
8716
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
8717
+ ```
8718
+
8719
+ *Effects:* Equivalent to: `return x.`*`inner_`*` == y.`*`inner_`*`;`
8720
+
8721
+ ``` cpp
8722
+ template<bool OtherConst>
8723
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
8724
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
8725
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
8726
+ template<bool OtherConst>
8727
+ requires sized_sentinel_for<zentinel<Const>, ziperator<OtherConst>>
8728
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
8729
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
8730
+ ```
8731
+
8732
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
8733
+
8734
+ ### Adjacent view <a id="range.adjacent">[[range.adjacent]]</a>
8735
+
8736
+ #### Overview <a id="range.adjacent.overview">[[range.adjacent.overview]]</a>
8737
+
8738
+ `adjacent_view` takes a view and produces a view whose Mᵗʰ element is a
8739
+ tuple of references to the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
8740
+ original view. If the original view has fewer than N elements, the
8741
+ resulting view is empty.
8742
+
8743
+ The name `views::adjacent<N>` denotes a range adaptor object
8744
+ [[range.adaptor.object]]. Given a subexpression `E` and a constant
8745
+ expression `N`, the expression `views::adjacent<N>(E)` is
8746
+ expression-equivalent to
8747
+
8748
+ - `((void)E, auto(views::empty<tuple<>>))` if `N` is equal to `0`,
8749
+ - otherwise, `adjacent_view<views::all_t<decltype((E))>, N>(E)`.
8750
+
8751
+ [*Example 1*:
8752
+
8753
+ ``` cpp
8754
+ vector v = {1, 2, 3, 4};
8755
+
8756
+ for (auto i : v | views::adjacent<2>) {
8757
+ cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints (1, 2) (2, 3) (3, 4)
8758
+ }
8759
+ ```
8760
+
8761
+ — *end example*]
8762
+
8763
+ Define `REPEAT(T, N)` as a pack of `N` types, each of which denotes the
8764
+ same type as `T`.
8765
+
8766
+ #### Class template `adjacent_view` <a id="range.adjacent.view">[[range.adjacent.view]]</a>
8767
+
8768
+ ``` cpp
8769
+ namespace std::ranges {
8770
+ template<forward_range V, size_t N>
8771
+ requires view<V> && (N > 0)
8772
+ class adjacent_view : public view_interface<adjacent_view<V, N>> {
8773
+ V base_ = V(); // exposition only
8774
+
8775
+ // [range.adjacent.iterator], class template adjacent_view::iterator
8776
+ template<bool> class iterator; // exposition only
8777
+
8778
+ // [range.adjacent.sentinel], class template adjacent_view::sentinel
8779
+ template<bool> class sentinel; // exposition only
8780
+
8781
+ struct as-sentinel{}; // exposition only
8782
+
8783
+ public:
8784
+ adjacent_view() requires default_initializable<V> = default;
8785
+ constexpr explicit adjacent_view(V base);
8786
+
8787
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
8788
+ constexpr V base() && { return std::move(base_); }
8789
+
8790
+ constexpr auto begin() requires (!simple-view<V>) {
8791
+ return iterator<false>(ranges::begin(base_), ranges::end(base_));
8792
+ }
8793
+
8794
+ constexpr auto begin() const requires range<const V> {
8795
+ return iterator<true>(ranges::begin(base_), ranges::end(base_));
8796
+ }
8797
+
8798
+ constexpr auto end() requires (!simple-view<V>) {
8799
+ if constexpr (common_range<V>) {
8800
+ return iterator<false>(as-sentinel{}, ranges::begin(base_), ranges::end(base_));
8801
+ } else {
8802
+ return sentinel<false>(ranges::end(base_));
8803
+ }
8804
+ }
8805
+
8806
+ constexpr auto end() const requires range<const V> {
8807
+ if constexpr (common_range<const V>) {
8808
+ return iterator<true>(as-sentinel{}, ranges::begin(base_), ranges::end(base_));
8809
+ } else {
8810
+ return sentinel<true>(ranges::end(base_));
8811
+ }
8812
+ }
8813
+
8814
+ constexpr auto size() requires sized_range<V>;
8815
+ constexpr auto size() const requires sized_range<const V>;
8816
+ };
8817
+ }
8818
+ ```
8819
+
8820
+ ``` cpp
8821
+ constexpr explicit adjacent_view(V base);
8822
+ ```
8823
+
8824
+ *Effects:* Initializes *base\_* with `std::move(base)`.
8825
+
8826
+ ``` cpp
8827
+ constexpr auto size() requires sized_range<V>;
8828
+ constexpr auto size() const requires sized_range<const V>;
8829
+ ```
8830
+
8831
+ *Effects:* Equivalent to:
8832
+
8833
+ ``` cpp
8834
+ using ST = decltype(ranges::size(base_));
8835
+ using CT = common_type_t<ST, size_t>;
8836
+ auto sz = static_cast<CT>(ranges::size(base_));
8837
+ sz -= std::min<CT>(sz, N - 1);
8838
+ return static_cast<ST>(sz);
8839
+ ```
8840
+
8841
+ #### Class template `adjacent_view::iterator` <a id="range.adjacent.iterator">[[range.adjacent.iterator]]</a>
8842
+
8843
+ ``` cpp
8844
+ namespace std::ranges {
8845
+ template<forward_range V, size_t N>
8846
+ requires view<V> && (N > 0)
8847
+ template<bool Const>
8848
+ class adjacent_view<V, N>::iterator {
8849
+ using Base = maybe-const<Const, V>; // exposition only
8850
+ array<iterator_t<Base>, N> current_ = array<iterator_t<Base>, N>(); // exposition only
8851
+ constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last); // exposition only
8852
+ constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
8853
+ // exposition only
8854
+ public:
8855
+ using iterator_category = input_iterator_tag;
8856
+ using iterator_concept = see below;
8857
+ using value_type = tuple<REPEAT(range_value_t<Base>, N)...>;
8858
+ using difference_type = range_difference_t<Base>;
8859
+
8860
+ iterator() = default;
8861
+ constexpr iterator(iterator<!Const> i)
8862
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
8863
+
8864
+ constexpr auto operator*() const;
8865
+ constexpr iterator& operator++();
8866
+ constexpr iterator operator++(int);
8867
+
8868
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
8869
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
8870
+
8871
+ constexpr iterator& operator+=(difference_type x)
8872
+ requires random_access_range<Base>;
8873
+ constexpr iterator& operator-=(difference_type x)
8874
+ requires random_access_range<Base>;
8875
+
8876
+ constexpr auto operator[](difference_type n) const
8877
+ requires random_access_range<Base>;
8878
+
8879
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
8880
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
8881
+ requires random_access_range<Base>;
8882
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
8883
+ requires random_access_range<Base>;
8884
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
8885
+ requires random_access_range<Base>;
8886
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
8887
+ requires random_access_range<Base>;
8888
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
8889
+ requires random_access_range<Base> &&
8890
+ three_way_comparable<iterator_t<Base>>;
8891
+
8892
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
8893
+ requires random_access_range<Base>;
8894
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
8895
+ requires random_access_range<Base>;
8896
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
8897
+ requires random_access_range<Base>;
8898
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
8899
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
8900
+
8901
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
8902
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
8903
+ requires indirectly_swappable<iterator_t<Base>>;
8904
+ };
8905
+ }
8906
+ ```
8907
+
8908
+ `iterator::iterator_concept` is defined as follows:
8909
+
8910
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
8911
+ denotes `random_access_iterator_tag`.
8912
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
8913
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
8914
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
8915
+
8916
+ If the invocation of any non-const member function of *`iterator`* exits
8917
+ via an exception, the *`iterator`* acquires a singular value.
8918
+
8919
+ ``` cpp
8920
+ constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last);
8921
+ ```
8922
+
8923
+ *Ensures:* *`current_`*`[0] == first` is `true`, and for every integer
8924
+ 1 ≤ i < `N`,
8925
+ *`current_`*`[`i`] == ranges::next(`*`current_`*`[`i`-1], 1, last)` is
8926
+ `true`.
8927
+
8928
+ ``` cpp
8929
+ constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
8930
+ ```
8931
+
8932
+ *Ensures:* If *Base* does not model `bidirectional_range`, each element
8933
+ of *current\_* is equal to *last*. Otherwise,
8934
+ *`current_`*`[N-1] == last` is `true`, and for every integer
8935
+ 0 ≤ i < (`N` - 1),
8936
+ *`current_`*`[`i`] == ranges::prev(`*`current_`*`[`i`+1], 1, first)` is
8937
+ `true`.
8938
+
8939
+ ``` cpp
8940
+ constexpr iterator(iterator<!Const> i)
8941
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
8942
+ ```
8943
+
8944
+ *Effects:* Initializes each element of *current\_* with the
8945
+ corresponding element of `i.`*`current_`* as an xvalue.
8946
+
8947
+ ``` cpp
8948
+ constexpr auto operator*() const;
8949
+ ```
8950
+
8951
+ *Effects:* Equivalent to:
8952
+
8953
+ ``` cpp
8954
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
8955
+ ```
8956
+
8957
+ ``` cpp
8958
+ constexpr iterator& operator++();
8959
+ ```
8960
+
8961
+ *Preconditions:* *`current_`*`.back()` is incrementable.
8962
+
8963
+ *Ensures:* Each element of *current\_* is equal to `ranges::next(i)`,
8964
+ where `i` is the value of that element before the call.
8965
+
8966
+ *Returns:* `*this`.
8967
+
8968
+ ``` cpp
8969
+ constexpr iterator operator++(int);
8970
+ ```
8971
+
8972
+ *Effects:* Equivalent to:
8973
+
8974
+ ``` cpp
8975
+ auto tmp = *this;
8976
+ ++*this;
8977
+ return tmp;
8978
+ ```
8979
+
8980
+ ``` cpp
8981
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
8982
+ ```
8983
+
8984
+ *Preconditions:* *`current_`*`.front()` is decrementable.
8985
+
8986
+ *Ensures:* Each element of *current\_* is equal to `ranges::prev(i)`,
8987
+ where `i` is the value of that element before the call.
8988
+
8989
+ *Returns:* `*this`.
8990
+
8991
+ ``` cpp
8992
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
8993
+ ```
8994
+
8995
+ *Effects:* Equivalent to:
8996
+
8997
+ ``` cpp
8998
+ auto tmp = *this;
8999
+ --*this;
9000
+ return tmp;
9001
+ ```
9002
+
9003
+ ``` cpp
9004
+ constexpr iterator& operator+=(difference_type x)
9005
+ requires random_access_range<Base>;
9006
+ ```
9007
+
9008
+ *Preconditions:* *`current_`*`.back() + x` has well-defined behavior.
9009
+
9010
+ *Ensures:* Each element of *current\_* is equal to `i + x`, where `i` is
9011
+ the value of that element before the call.
9012
+
9013
+ *Returns:* `*this`.
9014
+
9015
+ ``` cpp
9016
+ constexpr iterator& operator-=(difference_type x)
9017
+ requires random_access_range<Base>;
9018
+ ```
9019
+
9020
+ *Preconditions:* *`current_`*`.front() - x` has well-defined behavior.
9021
+
9022
+ *Ensures:* Each element of *current\_* is equal to `i - x`, where `i` is
9023
+ the value of that element before the call.
9024
+
9025
+ *Returns:* `*this`.
9026
+
9027
+ ``` cpp
9028
+ constexpr auto operator[](difference_type n) const
9029
+ requires random_access_range<Base>;
9030
+ ```
9031
+
9032
+ *Effects:* Equivalent to:
9033
+
9034
+ ``` cpp
9035
+ return tuple-transform([&](auto& i) -> decltype(auto) { return i[n]; }, current_);
9036
+ ```
9037
+
9038
+ ``` cpp
9039
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
9040
+ ```
9041
+
9042
+ *Returns:* `x.`*`current_`*`.back() == y.`*`current_`*`.back()`.
9043
+
9044
+ ``` cpp
9045
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
9046
+ requires random_access_range<Base>;
9047
+ ```
9048
+
9049
+ *Returns:* `x.`*`current_`*`.back() < y.`*`current_`*`.back()`.
9050
+
9051
+ ``` cpp
9052
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
9053
+ requires random_access_range<Base>;
9054
+ ```
9055
+
9056
+ *Effects:* Equivalent to: `return y < x;`
9057
+
9058
+ ``` cpp
9059
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
9060
+ requires random_access_range<Base>;
9061
+ ```
9062
+
9063
+ *Effects:* Equivalent to: `return !(y < x);`
9064
+
9065
+ ``` cpp
9066
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
9067
+ requires random_access_range<Base>;
9068
+ ```
9069
+
9070
+ *Effects:* Equivalent to: `return !(x < y);`
9071
+
9072
+ ``` cpp
9073
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
9074
+ requires random_access_range<Base> &&
9075
+ three_way_comparable<iterator_t<Base>>;
9076
+ ```
9077
+
9078
+ *Returns:* `x.`*`current_`*`.back() <=> y.`*`current_`*`.back()`.
9079
+
9080
+ ``` cpp
9081
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
9082
+ requires random_access_range<Base>;
9083
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
9084
+ requires random_access_range<Base>;
9085
+ ```
9086
+
9087
+ *Effects:* Equivalent to:
9088
+
9089
+ ``` cpp
9090
+ auto r = i;
9091
+ r += n;
9092
+ return r;
9093
+ ```
9094
+
9095
+ ``` cpp
9096
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
9097
+ requires random_access_range<Base>;
9098
+ ```
9099
+
9100
+ *Effects:* Equivalent to:
9101
+
9102
+ ``` cpp
9103
+ auto r = i;
9104
+ r -= n;
9105
+ return r;
9106
+ ```
9107
+
9108
+ ``` cpp
9109
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
9110
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
9111
+ ```
9112
+
9113
+ *Effects:* Equivalent to:
9114
+ `return x.`*`current_`*`.back() - y.`*`current_`*`.back();`
9115
+
9116
+ ``` cpp
9117
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
9118
+ ```
9119
+
9120
+ *Effects:* Equivalent to:
9121
+ `return `*`tuple-transform`*`(ranges::iter_move, i.`*`current_`*`);`
9122
+
9123
+ *Remarks:* The exception specification is equivalent to:
9124
+
9125
+ ``` cpp
9126
+ noexcept(ranges::iter_move(declval<const iterator_t<Base>&>())) &&
9127
+ is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>
9128
+ ```
9129
+
9130
+ ``` cpp
9131
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
9132
+ requires indirectly_swappable<iterator_t<Base>>;
9133
+ ```
9134
+
9135
+ *Preconditions:* None of the iterators in `l.`*`current_`* is equal to
9136
+ an iterator in `r.`*`current_`*.
9137
+
9138
+ *Effects:* For every integer 0 ≤ i < `N`, performs
9139
+ `ranges::iter_swap(l.`*`current_`*`[`i`], r.`*`current_`*`[`i`])`.
9140
+
9141
+ *Remarks:* The exception specification is equivalent to:
9142
+
9143
+ ``` cpp
9144
+ noexcept(ranges::iter_swap(declval<iterator_t<Base>>(), declval<iterator_t<Base>>()))
9145
+ ```
9146
+
9147
+ #### Class template `adjacent_view::sentinel` <a id="range.adjacent.sentinel">[[range.adjacent.sentinel]]</a>
9148
+
9149
+ ``` cpp
9150
+ namespace std::ranges {
9151
+ template<forward_range V, size_t N>
9152
+ requires view<V> && (N > 0)
9153
+ template<bool Const>
9154
+ class adjacent_view<V, N>::sentinel {
9155
+ using Base = maybe-const<Const, V>; // exposition only
9156
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
9157
+ constexpr explicit sentinel(sentinel_t<Base> end); // exposition only
9158
+
9159
+ public:
9160
+ sentinel() = default;
9161
+ constexpr sentinel(sentinel<!Const> i)
9162
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
9163
+
9164
+ template<bool OtherConst>
9165
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
9166
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
9167
+
9168
+ template<bool OtherConst>
9169
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
9170
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
9171
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
9172
+
9173
+ template<bool OtherConst>
9174
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
9175
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
9176
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
9177
+ };
9178
+ }
9179
+ ```
9180
+
9181
+ ``` cpp
9182
+ constexpr explicit sentinel(sentinel_t<Base> end);
9183
+ ```
9184
+
9185
+ *Effects:* Initializes *end\_* with `end`.
9186
+
9187
+ ``` cpp
9188
+ constexpr sentinel(sentinel<!Const> i)
9189
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
9190
+ ```
9191
+
9192
+ *Effects:* Initializes *end\_* with `std::move(i.`*`end_`*`)`.
9193
+
9194
+ ``` cpp
9195
+ template<bool OtherConst>
9196
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
9197
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
9198
+ ```
9199
+
9200
+ *Effects:* Equivalent to:
9201
+ `return x.`*`current_`*`.back() == y.`*`end_`*`;`
9202
+
9203
+ ``` cpp
9204
+ template<bool OtherConst>
9205
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
9206
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
9207
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
9208
+ ```
9209
+
9210
+ *Effects:* Equivalent to:
9211
+ `return x.`*`current_`*`.back() - y.`*`end_`*`;`
9212
+
9213
+ ``` cpp
9214
+ template<bool OtherConst>
9215
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
9216
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
9217
+ operator-(const sentinel& y, const iterator<OtherConst>& x);
9218
+ ```
9219
+
9220
+ *Effects:* Equivalent to:
9221
+ `return y.`*`end_`*` - x.`*`current_`*`.back();`
9222
+
9223
+ ### Adjacent transform view <a id="range.adjacent.transform">[[range.adjacent.transform]]</a>
9224
+
9225
+ #### Overview <a id="range.adjacent.transform.overview">[[range.adjacent.transform.overview]]</a>
9226
+
9227
+ `adjacent_transform_view` takes an invocable object and a view and
9228
+ produces a view whose Mᵗʰ element is the result of applying the
9229
+ invocable object to the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
9230
+ original view. If the original view has fewer than N elements, the
9231
+ resulting view is empty.
9232
+
9233
+ The name `views::adjacent_transform<N>` denotes a range adaptor object
9234
+ [[range.adaptor.object]]. Given subexpressions `E` and `F` and a
9235
+ constant expression `N`:
9236
+
9237
+ - If `N` is equal to `0`, `views::adjacent_transform<N>(E, F)` is
9238
+ expression-equivalent to `((void)E, views::zip_transform(F))`, except
9239
+ that the evaluations of `E` and `F` are indeterminately sequenced.
9240
+ - Otherwise, the expression `views::adjacent_transform<N>(E, F)` is
9241
+ expression-equivalent to
9242
+ `adjacent_transform_view<views::all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F)`.
9243
+
9244
+ [*Example 1*:
9245
+
9246
+ ``` cpp
9247
+ vector v = {1, 2, 3, 4};
9248
+
9249
+ for (auto i : v | views::adjacent_transform<2>(std::multiplies())) {
9250
+ cout << i << ' '; // prints 2 6 12
9251
+ }
9252
+ ```
9253
+
9254
+ — *end example*]
9255
+
9256
+ #### Class template `adjacent_transform_view` <a id="range.adjacent.transform.view">[[range.adjacent.transform.view]]</a>
9257
+
9258
+ ``` cpp
9259
+ namespace std::ranges {
9260
+ template<forward_range V, move_constructible F, size_t N>
9261
+ requires view<V> && (N > 0) && is_object_v<F> &&
9262
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
9263
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
9264
+ class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {
9265
+ movable-box<F> fun_; // exposition only
9266
+ adjacent_view<V, N> inner_; // exposition only
9267
+
9268
+ using InnerView = adjacent_view<V, N>; // exposition only
9269
+ template<bool Const>
9270
+ using inner-iterator = iterator_t<maybe-const<Const, InnerView>>; // exposition only
9271
+ template<bool Const>
9272
+ using inner-sentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only
9273
+
9274
+ // [range.adjacent.transform.iterator], class template adjacent_transform_view::iterator
9275
+ template<bool> class iterator; // exposition only
9276
+
9277
+ // [range.adjacent.transform.sentinel], class template adjacent_transform_view::sentinel
9278
+ template<bool> class sentinel; // exposition only
9279
+
9280
+ public:
9281
+ adjacent_transform_view() = default;
9282
+ constexpr explicit adjacent_transform_view(V base, F fun);
9283
+
9284
+ constexpr V base() const & requires copy_constructible<InnerView> { return inner_.base(); }
9285
+ constexpr V base() && { return std::move(inner_).base(); }
9286
+
9287
+ constexpr auto begin() {
9288
+ return iterator<false>(*this, inner_.begin());
9289
+ }
9290
+
9291
+ constexpr auto begin() const
9292
+ requires range<const InnerView> &&
9293
+ regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> {
9294
+ return iterator<true>(*this, inner_.begin());
9295
+ }
9296
+
9297
+ constexpr auto end() {
9298
+ if constexpr (common_range<InnerView>) {
9299
+ return iterator<false>(*this, inner_.end());
9300
+ } else {
9301
+ return sentinel<false>(inner_.end());
9302
+ }
9303
+ }
9304
+
9305
+ constexpr auto end() const
9306
+ requires range<const InnerView> &&
9307
+ regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> {
9308
+ if constexpr (common_range<const InnerView>) {
9309
+ return iterator<true>(*this, inner_.end());
9310
+ } else {
9311
+ return sentinel<true>(inner_.end());
9312
+ }
9313
+ }
9314
+
9315
+ constexpr auto size() requires sized_range<InnerView> {
9316
+ return inner_.size();
9317
+ }
9318
+
9319
+ constexpr auto size() const requires sized_range<const InnerView> {
9320
+ return inner_.size();
9321
+ }
9322
+ };
9323
+ }
9324
+ ```
9325
+
9326
+ ``` cpp
9327
+ constexpr explicit adjacent_transform_view(V base, F fun);
9328
+ ```
9329
+
9330
+ *Effects:* Initializes *fun\_* with `std::move(fun)` and *inner\_* with
9331
+ `std::move(base)`.
9332
+
9333
+ #### Class template `adjacent_transform_view::iterator` <a id="range.adjacent.transform.iterator">[[range.adjacent.transform.iterator]]</a>
9334
+
9335
+ ``` cpp
9336
+ namespace std::ranges {
9337
+ template<forward_range V, move_constructible F, size_t N>
9338
+ requires view<V> && (N > 0) && is_object_v<F> &&
9339
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
9340
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
9341
+ template<bool Const>
9342
+ class adjacent_transform_view<V, F, N>::iterator {
9343
+ using Parent = maybe-const<Const, adjacent_transform_view>; // exposition only
9344
+ using Base = maybe-const<Const, V>; // exposition only
9345
+ Parent* parent_ = nullptr; // exposition only
9346
+ inner-iterator<Const> inner_; // exposition only
9347
+
9348
+ constexpr iterator(Parent& parent, inner-iterator<Const> inner); // exposition only
9349
+
9350
+ public:
9351
+ using iterator_category = see below;
9352
+ using iterator_concept = typename inner-iterator<Const>::iterator_concept;
9353
+ using value_type =
9354
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
9355
+ REPEAT(range_reference_t<Base>, N)...>>;
9356
+ using difference_type = range_difference_t<Base>;
9357
+
9358
+ iterator() = default;
9359
+ constexpr iterator(iterator<!Const> i)
9360
+ requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
9361
+
9362
+ constexpr decltype(auto) operator*() const noexcept(see below);
9363
+ constexpr iterator& operator++();
9364
+ constexpr iterator operator++(int);
9365
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
9366
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
9367
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
9368
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
9369
+
9370
+ constexpr decltype(auto) operator[](difference_type n) const
9371
+ requires random_access_range<Base>;
9372
+
9373
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
9374
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
9375
+ requires random_access_range<Base>;
9376
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
9377
+ requires random_access_range<Base>;
9378
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
9379
+ requires random_access_range<Base>;
9380
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
9381
+ requires random_access_range<Base>;
9382
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
9383
+ requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
9384
+
9385
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
9386
+ requires random_access_range<Base>;
9387
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
9388
+ requires random_access_range<Base>;
9389
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
9390
+ requires random_access_range<Base>;
9391
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
9392
+ requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
9393
+ };
9394
+ }
9395
+ ```
9396
+
9397
+ The member *typedef-name* `iterator::iterator_category` is defined as
9398
+ follows:
9399
+
9400
+ - If `invoke_result_t<maybe-const<Const, F>&,
9401
+ REPEAT(range_reference_t<Base>, N)...>` isnot a reference,
9402
+ `iterator_category` denotes `input_iterator_tag`.
9403
+ - Otherwise, let `C` denote the type
9404
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
9405
+ - If `derived_from<C, random_access_iterator_tag>` is `true`,
9406
+ `iterator_category` denotes `random_access_iterator_tag`.
9407
+ - Otherwise, if `derived_from<C, bidirectional_iterator_tag>` is
9408
+ `true`, `iterator_category` denotes `bidirectional_iterator_tag`.
9409
+ - Otherwise, if `derived_from<C, forward_iterator_tag>` is `true`,
9410
+ `iterator_category` denotes `forward_iterator_tag`.
9411
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
9412
+
9413
+ ``` cpp
9414
+ constexpr iterator(Parent& parent, inner-iterator<Const> inner);
9415
+ ```
9416
+
9417
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and *inner\_*
9418
+ with `std::move(inner)`.
9419
+
9420
+ ``` cpp
9421
+ constexpr iterator(iterator<!Const> i)
9422
+ requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
9423
+ ```
9424
+
9425
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *inner\_*
9426
+ with `std::move(i.`*`inner_`*`)`.
9427
+
9428
+ ``` cpp
9429
+ constexpr decltype(auto) operator*() const noexcept(see below);
9430
+ ```
9431
+
9432
+ *Effects:* Equivalent to:
9433
+
9434
+ ``` cpp
9435
+ return apply([&](const auto&... iters) -> decltype(auto) {
9436
+ return invoke(*parent_->fun_, *iters...);
9437
+ }, inner_.current_);
9438
+ ```
9439
+
9440
+ *Remarks:* Let `Is` be the pack `0, 1, …, (N-1)`. The exception
9441
+ specification is equivalent to:
9442
+
9443
+ ``` cpp
9444
+ noexcept(invoke(*parent_->fun_, *std::get<Is>(inner_.current_)...))
9445
+ ```
9446
+
9447
+ ``` cpp
9448
+ constexpr iterator& operator++();
9449
+ ```
9450
+
9451
+ *Effects:* Equivalent to:
9452
+
9453
+ ``` cpp
9454
+ ++inner_;
9455
+ return *this;
9456
+ ```
9457
+
9458
+ ``` cpp
9459
+ constexpr iterator operator++(int);
9460
+ ```
9461
+
9462
+ *Effects:* Equivalent to:
9463
+
9464
+ ``` cpp
9465
+ auto tmp = *this;
9466
+ ++*this;
9467
+ return tmp;
9468
+ ```
9469
+
9470
+ ``` cpp
9471
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
9472
+ ```
9473
+
9474
+ *Effects:* Equivalent to:
9475
+
9476
+ ``` cpp
9477
+ --inner_;
9478
+ return *this;
9479
+ ```
9480
+
9481
+ ``` cpp
9482
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
9483
+ ```
9484
+
9485
+ *Effects:* Equivalent to:
9486
+
9487
+ ``` cpp
9488
+ auto tmp = *this;
9489
+ --*this;
9490
+ return tmp;
9491
+ ```
9492
+
9493
+ ``` cpp
9494
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
9495
+ ```
9496
+
9497
+ *Effects:* Equivalent to:
9498
+
9499
+ ``` cpp
9500
+ inner_ += x;
9501
+ return *this;
9502
+ ```
9503
+
9504
+ ``` cpp
9505
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
9506
+ ```
9507
+
9508
+ *Effects:* Equivalent to:
9509
+
9510
+ ``` cpp
9511
+ inner_ -= x;
9512
+ return *this;
9513
+ ```
9514
+
9515
+ ``` cpp
9516
+ constexpr decltype(auto) operator[](difference_type n) const
9517
+ requires random_access_range<Base>;
9518
+ ```
9519
+
9520
+ *Effects:* Equivalent to:
9521
+
9522
+ ``` cpp
9523
+ return apply([&](const auto&... iters) -> decltype(auto) {
9524
+ return invoke(*parent_->fun_, iters[n]...);
9525
+ }, inner_.current_);
9526
+ ```
9527
+
9528
+ ``` cpp
9529
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
9530
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
9531
+ requires random_access_range<Base>;
9532
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
9533
+ requires random_access_range<Base>;
9534
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
9535
+ requires random_access_range<Base>;
9536
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
9537
+ requires random_access_range<Base>;
9538
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
9539
+ requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
9540
+ ```
9541
+
9542
+ Let *op* be the operator.
9543
+
9544
+ *Effects:* Equivalent to:
9545
+ `return x.`*`inner_`*` `*`op`*` y.`*`inner_`*`;`
9546
+
9547
+ ``` cpp
9548
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
9549
+ requires random_access_range<Base>;
9550
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
9551
+ requires random_access_range<Base>;
9552
+ ```
9553
+
9554
+ *Effects:* Equivalent to:
9555
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` + n);`
9556
+
9557
+ ``` cpp
9558
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
9559
+ requires random_access_range<Base>;
9560
+ ```
9561
+
9562
+ *Effects:* Equivalent to:
9563
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` - n);`
9564
+
9565
+ ``` cpp
9566
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
9567
+ requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
9568
+ ```
9569
+
9570
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
9571
+
9572
+ #### Class template `adjacent_transform_view::sentinel` <a id="range.adjacent.transform.sentinel">[[range.adjacent.transform.sentinel]]</a>
9573
+
9574
+ ``` cpp
9575
+ namespace std::ranges {
9576
+ template<forward_range V, move_constructible F, size_t N>
9577
+ requires view<V> && (N > 0) && is_object_v<F> &&
9578
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
9579
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
9580
+ template<bool Const>
9581
+ class adjacent_transform_view<V, F, N>::sentinel {
9582
+ inner-sentinel<Const> inner_; // exposition only
9583
+ constexpr explicit sentinel(inner-sentinel<Const> inner); // exposition only
9584
+
9585
+ public:
9586
+ sentinel() = default;
9587
+ constexpr sentinel(sentinel<!Const> i)
9588
+ requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
9589
+
9590
+ template<bool OtherConst>
9591
+ requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
9592
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
9593
+
9594
+ template<bool OtherConst>
9595
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
9596
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
9597
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
9598
+
9599
+ template<bool OtherConst>
9600
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
9601
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
9602
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
9603
+ };
9604
+ }
9605
+ ```
9606
+
9607
+ ``` cpp
9608
+ constexpr explicit sentinel(inner-sentinel<Const> inner);
9609
+ ```
9610
+
9611
+ *Effects:* Initializes *inner\_* with `inner`.
9612
+
9613
+ ``` cpp
9614
+ constexpr sentinel(sentinel<!Const> i)
9615
+ requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
9616
+ ```
9617
+
9618
+ *Effects:* Initializes *inner\_* with `std::move(i.`*`inner_`*`)`.
9619
+
9620
+ ``` cpp
9621
+ template<bool OtherConst>
9622
+ requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
9623
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
9624
+ ```
9625
+
9626
+ *Effects:* Equivalent to `return x.`*`inner_`*` == y.`*`inner_`*`;`
9627
+
9628
+ ``` cpp
9629
+ template<bool OtherConst>
9630
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
9631
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
9632
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
9633
+
9634
+ template<bool OtherConst>
9635
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
9636
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
9637
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
9638
+ ```
9639
+
9640
+ *Effects:* Equivalent to `return x.`*`inner_`*` - y.`*`inner_`*`;`
9641
+
9642
+ ### Chunk view <a id="range.chunk">[[range.chunk]]</a>
9643
+
9644
+ #### Overview <a id="range.chunk.overview">[[range.chunk.overview]]</a>
9645
+
9646
+ `chunk_view` takes a view and a number N and produces a range of views
9647
+ that are N-sized non-overlapping successive chunks of the elements of
9648
+ the original view, in order. The last view in the range can have fewer
9649
+ than N elements.
9650
+
9651
+ The name `views::chunk` denotes a range adaptor object
9652
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
9653
+ expression `views::chunk(E, N)` is expression-equivalent to
9654
+ `chunk_view(E, N)`.
9655
+
9656
+ [*Example 1*:
9657
+
9658
+ ``` cpp
9659
+ vector v = {1, 2, 3, 4, 5};
9660
+
9661
+ for (auto r : v | views::chunk(2)) {
9662
+ cout << '[';
9663
+ auto sep = "";
9664
+ for (auto i : r) {
9665
+ cout << sep << i;
9666
+ sep = ", ";
9667
+ }
9668
+ cout << "] ";
9669
+ }
9670
+ // The above prints [1, 2] [3, 4] [5]
9671
+ ```
9672
+
9673
+ — *end example*]
9674
+
9675
+ #### Class template `chunk_view` for input ranges <a id="range.chunk.view.input">[[range.chunk.view.input]]</a>
9676
+
9677
+ ``` cpp
9678
+ namespace std::ranges {
9679
+ template<class I>
9680
+ constexpr I div-ceil(I num, I denom) { // exposition only
9681
+ I r = num / denom;
9682
+ if (num % denom)
9683
+ ++r;
9684
+ return r;
9685
+ }
9686
+
9687
+ template<view V>
9688
+ requires input_range<V>
9689
+ class chunk_view : public view_interface<chunk_view<V>> {
9690
+ V base_; // exposition only
9691
+ range_difference_t<V> n_; // exposition only
9692
+ range_difference_t<V> remainder_ = 0; // exposition only
9693
+
9694
+ non-propagating-cache<iterator_t<V>> current_; // exposition only
9695
+
9696
+ // [range.chunk.outer.iter], class chunk_view::outer-iterator
9697
+ class outer-iterator; // exposition only
9698
+
9699
+ // [range.chunk.inner.iter], class chunk_view::inner-iterator
9700
+ class inner-iterator; // exposition only
9701
+
9702
+ public:
9703
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
9704
+
9705
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
9706
+ constexpr V base() && { return std::move(base_); }
9707
+
9708
+ constexpr outer-iterator begin();
9709
+ constexpr default_sentinel_t end() const noexcept;
9710
+
9711
+ constexpr auto size() requires sized_range<V>;
9712
+ constexpr auto size() const requires sized_range<const V>;
9713
+ };
9714
+
9715
+ template<class R>
9716
+ chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;
9717
+ }
9718
+ ```
9719
+
9720
+ ``` cpp
9721
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
9722
+ ```
9723
+
9724
+ *Preconditions:* `n > 0` is `true`.
9725
+
9726
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
9727
+ `n`.
9728
+
9729
+ ``` cpp
9730
+ constexpr outer-iterator begin();
9731
+ ```
9732
+
9733
+ *Effects:* Equivalent to:
9734
+
9735
+ ``` cpp
9736
+ current_ = ranges::begin(base_);
9737
+ remainder_ = n_;
9738
+ return outer-iterator(*this);
9739
+ ```
9740
+
9741
+ ``` cpp
9742
+ constexpr default_sentinel_t end() const noexcept;
9743
+ ```
9744
+
9745
+ *Returns:* `default_sentinel`.
9746
+
9747
+ ``` cpp
9748
+ constexpr auto size() requires sized_range<V>;
9749
+ constexpr auto size() const requires sized_range<const V>;
9750
+ ```
9751
+
9752
+ *Effects:* Equivalent to:
9753
+
9754
+ ``` cpp
9755
+ return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
9756
+ ```
9757
+
9758
+ #### Class `chunk_view::outer-iterator` <a id="range.chunk.outer.iter">[[range.chunk.outer.iter]]</a>
9759
+
9760
+ ``` cpp
9761
+ namespace std::ranges {
9762
+ template<view V>
9763
+ requires input_range<V>
9764
+ class chunk_view<V>::outer-iterator {
9765
+ chunk_view* parent_; // exposition only
9766
+
9767
+ constexpr explicit outer-iterator(chunk_view& parent); // exposition only
9768
+
9769
+ public:
9770
+ using iterator_concept = input_iterator_tag;
9771
+ using difference_type = range_difference_t<V>;
9772
+
9773
+ // [range.chunk.outer.value], class chunk_view::outer-iterator::value_type
9774
+ struct value_type;
9775
+
9776
+ outer-iterator(outer-iterator&&) = default;
9777
+ outer-iterator& operator=(outer-iterator&&) = default;
9778
+
9779
+ constexpr value_type operator*() const;
9780
+ constexpr outer-iterator& operator++();
9781
+ constexpr void operator++(int);
9782
+
9783
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
9784
+
9785
+ friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)
9786
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9787
+ friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)
9788
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9789
+ };
9790
+ }
9791
+ ```
9792
+
9793
+ ``` cpp
9794
+ constexpr explicit outer-iterator(chunk_view& parent);
9795
+ ```
9796
+
9797
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
9798
+
9799
+ ``` cpp
9800
+ constexpr value_type operator*() const;
9801
+ ```
9802
+
9803
+ *Preconditions:* `*this == default_sentinel` is `false`.
9804
+
9805
+ *Returns:* `value_type(*`*`parent_`*`)`.
9806
+
9807
+ ``` cpp
9808
+ constexpr outer-iterator& operator++();
9809
+ ```
9810
+
9811
+ *Preconditions:* `*this == default_sentinel` is `false`.
9812
+
9813
+ *Effects:* Equivalent to:
9814
+
9815
+ ``` cpp
9816
+ ranges::advance(*parent_->current_, parent_->remainder_, ranges::end(parent_->base_));
9817
+ parent_->remainder_ = parent_->n_;
9818
+ return *this;
9819
+ ```
9820
+
9821
+ ``` cpp
9822
+ constexpr void operator++(int);
9823
+ ```
9824
+
9825
+ *Effects:* Equivalent to `++*this`.
9826
+
9827
+ ``` cpp
9828
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
9829
+ ```
9830
+
9831
+ *Effects:* Equivalent to:
9832
+
9833
+ ``` cpp
9834
+ return *x.parent_->current_ == ranges::end(x.parent_->base_) && x.parent_->remainder_ != 0;
9835
+ ```
9836
+
9837
+ ``` cpp
9838
+ friend constexpr difference_type operator-(default_sentinel_t y, const outer-iterator& x)
9839
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9840
+ ```
9841
+
9842
+ *Effects:* Equivalent to:
9843
+
9844
+ ``` cpp
9845
+ const auto dist = ranges::end(x.parent_->base_) - *x.parent_->current_;
9846
+ if (dist < x.parent_->remainder_) {
9847
+ return dist == 0 ? 0 : 1;
9848
+ }
9849
+ return div-ceil(dist - x.parent_->remainder_, x.parent_->n_) + 1;
9850
+ ```
9851
+
9852
+ ``` cpp
9853
+ friend constexpr difference_type operator-(const outer-iterator& x, default_sentinel_t y)
9854
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9855
+ ```
9856
+
9857
+ *Effects:* Equivalent to: `return -(y - x);`
9858
+
9859
+ #### Class `chunk_view::outer-iterator::value_type` <a id="range.chunk.outer.value">[[range.chunk.outer.value]]</a>
9860
+
9861
+ ``` cpp
9862
+ namespace std::ranges {
9863
+ template<view V>
9864
+ requires input_range<V>
9865
+ struct chunk_view<V>::outer-iterator::value_type : view_interface<value_type> {
9866
+ private:
9867
+ chunk_view* parent_; // exposition only
9868
+
9869
+ constexpr explicit value_type(chunk_view& parent); // exposition only
9870
+
9871
+ public:
9872
+ constexpr inner-iterator begin() const noexcept;
9873
+ constexpr default_sentinel_t end() const noexcept;
9874
+
9875
+ constexpr auto size() const
9876
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9877
+ };
9878
+ }
9879
+ ```
9880
+
9881
+ ``` cpp
9882
+ constexpr explicit value_type(chunk_view& parent);
9883
+ ```
9884
+
9885
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
9886
+
9887
+ ``` cpp
9888
+ constexpr inner-iterator begin() const noexcept;
9889
+ ```
9890
+
9891
+ *Returns:* *`inner-iterator`*`(*`*`parent_`*`)`.
9892
+
9893
+ ``` cpp
9894
+ constexpr default_sentinel_t end() const noexcept;
9895
+ ```
9896
+
9897
+ *Returns:* `default_sentinel`.
9898
+
9899
+ ``` cpp
9900
+ constexpr auto size() const
9901
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9902
+ ```
9903
+
9904
+ *Effects:* Equivalent to:
9905
+
9906
+ ``` cpp
9907
+ return to-unsigned-like(ranges::min(parent_->remainder_,
9908
+ ranges::end(parent_->base_) - *parent_->current_));
9909
+ ```
9910
+
9911
+ #### Class `chunk_view::inner-iterator` <a id="range.chunk.inner.iter">[[range.chunk.inner.iter]]</a>
9912
+
9913
+ ``` cpp
9914
+ namespace std::ranges {
9915
+ template<view V>
9916
+ requires input_range<V>
9917
+ class chunk_view<V>::inner-iterator {
9918
+ chunk_view* parent_; // exposition only
9919
+
9920
+ constexpr explicit inner-iterator(chunk_view& parent) noexcept; // exposition only
9921
+
9922
+ public:
9923
+ using iterator_concept = input_iterator_tag;
9924
+ using difference_type = range_difference_t<V>;
9925
+ using value_type = range_value_t<V>;
9926
+
9927
+ inner-iterator(inner-iterator&&) = default;
9928
+ inner-iterator& operator=(inner-iterator&&) = default;
9929
+
9930
+ constexpr const iterator_t<V>& base() const &;
9931
+
9932
+ constexpr range_reference_t<V> operator*() const;
9933
+ constexpr inner-iterator& operator++();
9934
+ constexpr void operator++(int);
9935
+
9936
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
9937
+
9938
+ friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)
9939
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9940
+ friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)
9941
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
9942
+
9943
+ friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i)
9944
+ noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
9945
+
9946
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
9947
+ noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))
9948
+ requires indirectly_swappable<iterator_t<V>>;
9949
+ };
9950
+ }
9951
+ ```
9952
+
9953
+ ``` cpp
9954
+ constexpr explicit inner-iterator(chunk_view& parent) noexcept;
9955
+ ```
9956
+
9957
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
9958
+
9959
+ ``` cpp
9960
+ constexpr const iterator_t<V>& base() const &;
9961
+ ```
9962
+
9963
+ *Effects:* Equivalent to: `return *`*`parent_`*`->`*`current_`*`;`
9964
+
9965
+ ``` cpp
9966
+ constexpr range_reference_t<V> operator*() const;
9967
+ ```
9968
+
9969
+ *Preconditions:* `*this == default_sentinel` is `false`.
9970
+
9971
+ *Effects:* Equivalent to: `return **`*`parent_`*`->`*`current_`*`;`
9972
+
9973
+ ``` cpp
9974
+ constexpr inner-iterator& operator++();
9975
+ ```
9976
+
9977
+ *Preconditions:* `*this == default_sentinel` is `false`.
9978
+
9979
+ *Effects:* Equivalent to:
9980
+
9981
+ ``` cpp
9982
+ ++*parent_->current_;
9983
+ if (*parent_->current_ == ranges::end(parent_->base_))
9984
+ parent_->remainder_ = 0;
9985
+ else
9986
+ --parent_->remainder_;
9987
+ return *this;
9988
+ ```
9989
+
9990
+ ``` cpp
9991
+ constexpr void operator++(int);
9992
+ ```
9993
+
9994
+ *Effects:* Equivalent to `++*this`.
9995
+
9996
+ ``` cpp
9997
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
9998
+ ```
9999
+
10000
+ *Returns:* `x.`*`parent_`*`->`*`remainder_`*` == 0`.
10001
+
10002
+ ``` cpp
10003
+ friend constexpr difference_type operator-(default_sentinel_t y, const inner-iterator& x)
10004
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10005
+ ```
10006
+
10007
+ *Effects:* Equivalent to:
10008
+
10009
+ ``` cpp
10010
+ return ranges::min(x.parent_->remainder_,
10011
+ ranges::end(x.parent_->base_) - *x.parent_->current_);
10012
+ ```
10013
+
10014
+ ``` cpp
10015
+ friend constexpr difference_type operator-(const inner-iterator& x, default_sentinel_t y)
10016
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10017
+ ```
10018
+
10019
+ *Effects:* Equivalent to: `return -(y - x);`
10020
+
10021
+ ``` cpp
10022
+ friend constexpr range_rvalue_reference_t<V> iter_move(const inner-iterator& i)
10023
+ noexcept(noexcept(ranges::iter_move(*i.parent_->current_)));
10024
+ ```
10025
+
10026
+ *Effects:* Equivalent to:
10027
+ `return ranges::iter_move(*i.`*`parent_`*`->`*`current_`*`);`
10028
+
10029
+ ``` cpp
10030
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
10031
+ noexcept(noexcept(ranges::iter_swap(*x.parent_->current_, *y.parent_->current_)))
10032
+ requires indirectly_swappable<iterator_t<V>>;
10033
+ ```
10034
+
10035
+ *Effects:* Equivalent to:
10036
+ `ranges::iter_swap(*x.`*`parent_`*`->`*`current_`*`, *y.`*`parent_`*`->`*`current_`*`);`
10037
+
10038
+ #### Class template `chunk_view` for forward ranges <a id="range.chunk.view.fwd">[[range.chunk.view.fwd]]</a>
10039
+
10040
+ ``` cpp
10041
+ namespace std::ranges {
10042
+ template<view V>
10043
+ requires forward_range<V>
10044
+ class chunk_view<V> : public view_interface<chunk_view<V>> {
10045
+ V base_; // exposition only
10046
+ range_difference_t<V> n_; // exposition only
10047
+
10048
+ // [range.chunk.fwd.iter], class template chunk_view::iterator
10049
+ template<bool> class iterator; // exposition only
10050
+
10051
+ public:
10052
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
10053
+
10054
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
10055
+ constexpr V base() && { return std::move(base_); }
10056
+
10057
+ constexpr auto begin() requires (!simple-view<V>) {
10058
+ return iterator<false>(this, ranges::begin(base_));
10059
+ }
10060
+
10061
+ constexpr auto begin() const requires forward_range<const V> {
10062
+ return iterator<true>(this, ranges::begin(base_));
10063
+ }
10064
+
10065
+ constexpr auto end() requires (!simple-view<V>) {
10066
+ if constexpr (common_range<V> && sized_range<V>) {
10067
+ auto missing = (n_ - ranges::distance(base_) % n_) % n_;
10068
+ return iterator<false>(this, ranges::end(base_), missing);
10069
+ } else if constexpr (common_range<V> && !bidirectional_range<V>) {
10070
+ return iterator<false>(this, ranges::end(base_));
10071
+ } else {
10072
+ return default_sentinel;
10073
+ }
10074
+ }
10075
+
10076
+ constexpr auto end() const requires forward_range<const V> {
10077
+ if constexpr (common_range<const V> && sized_range<const V>) {
10078
+ auto missing = (n_ - ranges::distance(base_) % n_) % n_;
10079
+ return iterator<true>(this, ranges::end(base_), missing);
10080
+ } else if constexpr (common_range<const V> && !bidirectional_range<const V>) {
10081
+ return iterator<true>(this, ranges::end(base_));
10082
+ } else {
10083
+ return default_sentinel;
10084
+ }
10085
+ }
10086
+
10087
+ constexpr auto size() requires sized_range<V>;
10088
+ constexpr auto size() const requires sized_range<const V>;
10089
+ };
10090
+ }
10091
+ ```
10092
+
10093
+ ``` cpp
10094
+ constexpr explicit chunk_view(V base, range_difference_t<V> n);
10095
+ ```
10096
+
10097
+ *Preconditions:* `n > 0` is `true`.
10098
+
10099
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
10100
+ `n`.
10101
+
10102
+ ``` cpp
10103
+ constexpr auto size() requires sized_range<V>;
10104
+ constexpr auto size() const requires sized_range<const V>;
10105
+ ```
10106
+
10107
+ *Effects:* Equivalent to:
10108
+
10109
+ ``` cpp
10110
+ return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
10111
+ ```
10112
+
10113
+ #### Class template `chunk_view::iterator` for forward ranges <a id="range.chunk.fwd.iter">[[range.chunk.fwd.iter]]</a>
10114
+
10115
+ ``` cpp
10116
+ namespace std::ranges {
10117
+ template<view V>
10118
+ requires forward_range<V>
10119
+ template<bool Const>
10120
+ class chunk_view<V>::iterator {
10121
+ using Parent = maybe-const<Const, chunk_view>; // exposition only
10122
+ using Base = maybe-const<Const, V>; // exposition only
10123
+
10124
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
10125
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
10126
+ range_difference_t<Base> n_ = 0; // exposition only
10127
+ range_difference_t<Base> missing_ = 0; // exposition only
10128
+
10129
+ constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only
10130
+ range_difference_t<Base> missing = 0);
10131
+
10132
+ public:
10133
+ using iterator_category = input_iterator_tag;
10134
+ using iterator_concept = see below;
10135
+ using value_type = decltype(views::take(subrange(current_, end_), n_));
10136
+ using difference_type = range_difference_t<Base>;
10137
+
10138
+ iterator() = default;
10139
+ constexpr iterator(iterator<!Const> i)
10140
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
10141
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
10142
+
10143
+ constexpr iterator_t<Base> base() const;
10144
+
10145
+ constexpr value_type operator*() const;
10146
+ constexpr iterator& operator++();
10147
+ constexpr iterator operator++(int);
10148
+
10149
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
10150
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
10151
+
10152
+ constexpr iterator& operator+=(difference_type x)
10153
+ requires random_access_range<Base>;
10154
+ constexpr iterator& operator-=(difference_type x)
10155
+ requires random_access_range<Base>;
10156
+
10157
+ constexpr value_type operator[](difference_type n) const
10158
+ requires random_access_range<Base>;
10159
+
10160
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
10161
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
10162
+
10163
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
10164
+ requires random_access_range<Base>;
10165
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
10166
+ requires random_access_range<Base>;
10167
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
10168
+ requires random_access_range<Base>;
10169
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
10170
+ requires random_access_range<Base>;
10171
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
10172
+ requires random_access_range<Base> &&
10173
+ three_way_comparable<iterator_t<Base>>;
10174
+
10175
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
10176
+ requires random_access_range<Base>;
10177
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
10178
+ requires random_access_range<Base>;
10179
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
10180
+ requires random_access_range<Base>;
10181
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
10182
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
10183
+
10184
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
10185
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10186
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
10187
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10188
+ };
10189
+ }
10190
+ ```
10191
+
10192
+ `iterator::iterator_concept` is defined as follows:
10193
+
10194
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
10195
+ denotes `random_access_iterator_tag`.
10196
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
10197
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
10198
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
10199
+
10200
+ ``` cpp
10201
+ constexpr iterator(Parent* parent, iterator_t<Base> current,
10202
+ range_difference_t<Base> missing = 0);
10203
+ ```
10204
+
10205
+ *Effects:* Initializes *current\_* with `current`, *end\_* with
10206
+ `ranges::end(parent->`*`base_`*`)`, *n\_* with `parent->`*`n_`*, and
10207
+ *missing\_* with `missing`.
10208
+
10209
+ ``` cpp
10210
+ constexpr iterator(iterator<!Const> i)
10211
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
10212
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
10213
+ ```
10214
+
10215
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`,
10216
+ *end\_* with `std::move(i.`*`end_`*`)`, *n\_* with `i.`*`n_`*, and
10217
+ *missing\_* with `i.`*`missing_`*.
10218
+
10219
+ ``` cpp
10220
+ constexpr iterator_t<Base> base() const;
10221
+ ```
10222
+
10223
+ *Returns:* *current\_*.
10224
+
10225
+ ``` cpp
10226
+ constexpr value_type operator*() const;
10227
+ ```
10228
+
10229
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
10230
+
10231
+ *Returns:*
10232
+ `views::take(subrange(`*`current_`*`, `*`end_`*`), `*`n_`*`)`.
10233
+
10234
+ ``` cpp
10235
+ constexpr iterator& operator++();
10236
+ ```
10237
+
10238
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
10239
+
10240
+ *Effects:* Equivalent to:
10241
+
10242
+ ``` cpp
10243
+ missing_ = ranges::advance(current_, n_, end_);
10244
+ return *this;
10245
+ ```
10246
+
10247
+ ``` cpp
10248
+ constexpr iterator operator++(int);
10249
+ ```
10250
+
10251
+ *Effects:* Equivalent to:
10252
+
10253
+ ``` cpp
10254
+ auto tmp = *this;
10255
+ ++*this;
10256
+ return tmp;
10257
+ ```
10258
+
10259
+ ``` cpp
10260
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
10261
+ ```
10262
+
10263
+ *Effects:* Equivalent to:
10264
+
10265
+ ``` cpp
10266
+ ranges::advance(current_, missing_ - n_);
10267
+ missing_ = 0;
10268
+ return *this;
10269
+ ```
10270
+
10271
+ ``` cpp
10272
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
10273
+ ```
10274
+
10275
+ *Effects:* Equivalent to:
10276
+
10277
+ ``` cpp
10278
+ auto tmp = *this;
10279
+ --*this;
10280
+ return tmp;
10281
+ ```
10282
+
10283
+ ``` cpp
10284
+ constexpr iterator& operator+=(difference_type x)
10285
+ requires random_access_range<Base>;
10286
+ ```
10287
+
10288
+ *Preconditions:* If `x` is positive,
10289
+ `ranges::distance(`*`current_`*`, `*`end_`*`) > `*`n_`*` * (x - 1)` is
10290
+ `true`.
10291
+
10292
+ [*Note 1*: If `x` is negative, the *Effects* paragraph implies a
10293
+ precondition. — *end note*]
10294
+
10295
+ *Effects:* Equivalent to:
10296
+
10297
+ ``` cpp
10298
+ if (x > 0) {
10299
+ ranges::advance(current_, n_ * (x - 1));
10300
+ missing_ = ranges::advance(current_, n_, end_);
10301
+ } else if (x < 0) {
10302
+ ranges::advance(current_, n_ * x + missing_);
10303
+ missing_ = 0;
10304
+ }
10305
+ return *this;
10306
+ ```
10307
+
10308
+ ``` cpp
10309
+ constexpr iterator& operator-=(difference_type x)
10310
+ requires random_access_range<Base>;
10311
+ ```
10312
+
10313
+ *Effects:* Equivalent to: `return *this += -x;`
10314
+
10315
+ ``` cpp
10316
+ constexpr value_type operator[](difference_type n) const
10317
+ requires random_access_range<Base>;
10318
+ ```
10319
+
10320
+ *Returns:* `*(*this + n)`.
10321
+
10322
+ ``` cpp
10323
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
10324
+ ```
10325
+
10326
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
10327
+
10328
+ ``` cpp
10329
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
10330
+ ```
10331
+
10332
+ *Returns:* `x.`*`current_`*` == x.`*`end_`*.
10333
+
10334
+ ``` cpp
10335
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
10336
+ requires random_access_range<Base>;
10337
+ ```
10338
+
10339
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
10340
+
10341
+ ``` cpp
10342
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
10343
+ requires random_access_range<Base>;
10344
+ ```
10345
+
10346
+ *Effects:* Equivalent to: `return y < x;`
10347
+
10348
+ ``` cpp
10349
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
10350
+ requires random_access_range<Base>;
10351
+ ```
10352
+
10353
+ *Effects:* Equivalent to: `return !(y < x);`
10354
+
10355
+ ``` cpp
10356
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
10357
+ requires random_access_range<Base>;
10358
+ ```
10359
+
10360
+ *Effects:* Equivalent to: `return !(x < y);`
10361
+
10362
+ ``` cpp
10363
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
10364
+ requires random_access_range<Base> &&
10365
+ three_way_comparable<iterator_t<Base>>;
10366
+ ```
10367
+
10368
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
10369
+
10370
+ ``` cpp
10371
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
10372
+ requires random_access_range<Base>;
10373
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
10374
+ requires random_access_range<Base>;
10375
+ ```
10376
+
10377
+ *Effects:* Equivalent to:
10378
+
10379
+ ``` cpp
10380
+ auto r = i;
10381
+ r += n;
10382
+ return r;
10383
+ ```
10384
+
10385
+ ``` cpp
10386
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
10387
+ requires random_access_range<Base>;
10388
+ ```
10389
+
10390
+ *Effects:* Equivalent to:
10391
+
10392
+ ``` cpp
10393
+ auto r = i;
10394
+ r -= n;
10395
+ return r;
10396
+ ```
10397
+
10398
+ ``` cpp
10399
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
10400
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
10401
+ ```
10402
+
10403
+ *Returns:*
10404
+ `(x.`*`current_`*` - y.`*`current_`*` + x.`*`missing_`*` - y.`*`missing_`*`) / x.`*`n_`*.
10405
+
10406
+ ``` cpp
10407
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
10408
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10409
+ ```
10410
+
10411
+ *Returns:* *`div-ceil`*`(x.`*`end_`*` - x.`*`current_`*`, x.`*`n_`*`)`.
10412
+
10413
+ ``` cpp
10414
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
10415
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10416
+ ```
10417
+
10418
+ *Effects:* Equivalent to: `return -(y - x);`
10419
+
10420
+ ### Slide view <a id="range.slide">[[range.slide]]</a>
10421
+
10422
+ #### Overview <a id="range.slide.overview">[[range.slide.overview]]</a>
10423
+
10424
+ `slide_view` takes a view and a number N and produces a view whose Mᵗʰ
10425
+ element is a view over the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
10426
+ original view. If the original view has fewer than N elements, the
10427
+ resulting view is empty.
10428
+
10429
+ The name `views::slide` denotes a range adaptor object
10430
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
10431
+ expression `views::slide(E, N)` is expression-equivalent to
10432
+ `slide_view(E, N)`.
10433
+
10434
+ [*Example 1*:
10435
+
10436
+ ``` cpp
10437
+ vector v = {1, 2, 3, 4};
10438
+
10439
+ for (auto i : v | views::slide(2)) {
10440
+ cout << '[' << i[0] << ", " << i[1] << "] "; // prints [1, 2] [2, 3] [3, 4]
10441
+ }
10442
+ ```
10443
+
10444
+ — *end example*]
10445
+
10446
+ #### Class template `slide_view` <a id="range.slide.view">[[range.slide.view]]</a>
10447
+
10448
+ ``` cpp
10449
+ namespace std::ranges {
10450
+ template<class V>
10451
+ concept slide-caches-nothing = random_access_range<V> && sized_range<V>; // exposition only
10452
+
10453
+ template<class V>
10454
+ concept slide-caches-last = // exposition only
10455
+ !slide-caches-nothing<V> && bidirectional_range<V> && common_range<V>;
10456
+
10457
+ template<class V>
10458
+ concept slide-caches-first = // exposition only
10459
+ !slide-caches-nothing<V> && !slide-caches-last<V>;
10460
+
10461
+ template<forward_range V>
10462
+ requires view<V>
10463
+ class slide_view : public view_interface<slide_view<V>> {
10464
+ V base_; // exposition only
10465
+ range_difference_t<V> n_; // exposition only
10466
+
10467
+ // [range.slide.iterator], class template slide_view::iterator
10468
+ template<bool> class iterator; // exposition only
10469
+
10470
+ // [range.slide.sentinel], class slide_view::sentinel
10471
+ class sentinel; // exposition only
10472
+
10473
+ public:
10474
+ constexpr explicit slide_view(V base, range_difference_t<V> n);
10475
+
10476
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
10477
+ constexpr V base() && { return std::move(base_); }
10478
+
10479
+ constexpr auto begin()
10480
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
10481
+ constexpr auto begin() const requires slide-caches-nothing<const V>;
10482
+
10483
+ constexpr auto end()
10484
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
10485
+ constexpr auto end() const requires slide-caches-nothing<const V>;
10486
+
10487
+ constexpr auto size() requires sized_range<V>;
10488
+ constexpr auto size() const requires sized_range<const V>;
10489
+ };
10490
+
10491
+ template<class R>
10492
+ slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>;
10493
+ }
10494
+ ```
10495
+
10496
+ ``` cpp
10497
+ constexpr explicit slide_view(V base, range_difference_t<V> n);
10498
+ ```
10499
+
10500
+ *Preconditions:* `n > 0` is `true`.
10501
+
10502
+ *Effects:* Initializes *base\_* with `std::move(base)` and *n\_* with
10503
+ `n`.
10504
+
10505
+ ``` cpp
10506
+ constexpr auto begin()
10507
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
10508
+ ```
10509
+
10510
+ *Returns:*
10511
+
10512
+ - If `V` models `slide-caches-first`,
10513
+ ``` cpp
10514
+ iterator<false>(ranges::begin(base_),
10515
+ ranges::next(ranges::begin(base_), n_ - 1, ranges::end(base_)), n_)
10516
+ ```
10517
+ - Otherwise,
10518
+ *`iterator`*`<false>(ranges::begin(`*`base_`*`), `*`n_`*`)`.
10519
+
10520
+ *Remarks:* In order to provide the amortized constant-time complexity
10521
+ required by the `range` concept, this function caches the result within
10522
+ the `slide_view` for use on subsequent calls when `V` models
10523
+ `slide-caches-first`.
10524
+
10525
+ ``` cpp
10526
+ constexpr auto begin() const requires slide-caches-nothing<const V>;
10527
+ ```
10528
+
10529
+ *Returns:* *`iterator`*`<true>(ranges::begin(`*`base_`*`), `*`n_`*`)`.
10530
+
10531
+ ``` cpp
10532
+ constexpr auto end()
10533
+ requires (!(simple-view<V> && slide-caches-nothing<const V>));
10534
+ ```
10535
+
10536
+ *Returns:*
10537
+
10538
+ - If `V` models `slide-caches-nothing`,
10539
+ ``` cpp
10540
+ iterator<false>(ranges::begin(base_) + range_difference_t<V>(size()), n_)
10541
+ ```
10542
+ - Otherwise, if `V` models `slide-caches-last`,
10543
+ ``` cpp
10544
+ iterator<false>(ranges::prev(ranges::end(base_), n_ - 1, ranges::begin(base_)), n_)
10545
+ ```
10546
+ - Otherwise, if `V` models `common_range`,
10547
+ ``` cpp
10548
+ iterator<false>(ranges::end(base_), ranges::end(base_), n_)
10549
+ ```
10550
+ - Otherwise, *`sentinel`*`(ranges::end(`*`base_`*`))`.
10551
+
10552
+ *Remarks:* In order to provide the amortized constant-time complexity
10553
+ required by the `range` concept, this function caches the result within
10554
+ the `slide_view` for use on subsequent calls when `V` models
10555
+ `slide-caches-last`.
10556
+
10557
+ ``` cpp
10558
+ constexpr auto end() const requires slide-caches-nothing<const V>;
10559
+ ```
10560
+
10561
+ *Returns:* `begin() + range_difference_t<const V>(size())`.
10562
+
10563
+ ``` cpp
10564
+ constexpr auto size() requires sized_range<V>;
10565
+ constexpr auto size() const requires sized_range<const V>;
10566
+ ```
10567
+
10568
+ *Effects:* Equivalent to:
10569
+
10570
+ ``` cpp
10571
+ auto sz = ranges::distance(base_) - n_ + 1;
10572
+ if (sz < 0) sz = 0;
10573
+ return to-unsigned-like(sz);
10574
+ ```
10575
+
10576
+ #### Class template `slide_view::iterator` <a id="range.slide.iterator">[[range.slide.iterator]]</a>
10577
+
10578
+ ``` cpp
10579
+ namespace std::ranges {
10580
+ template<forward_range V>
10581
+ requires view<V>
10582
+ template<bool Const>
10583
+ class slide_view<V>::iterator {
10584
+ using Base = maybe-const<Const, V>; // exposition only
10585
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
10586
+ iterator_t<Base> last_ele_ = iterator_t<Base>(); // exposition only,
10587
+ // present only if Base models slide-caches-first
10588
+ range_difference_t<Base> n_ = 0; // exposition only
10589
+
10590
+ constexpr iterator(iterator_t<Base> current, range_difference_t<Base> n) // exposition only
10591
+ requires (!slide-caches-first<Base>);
10592
+
10593
+ constexpr iterator(iterator_t<Base> current, iterator_t<Base> last_ele, // exposition only
10594
+ range_difference_t<Base> n)
10595
+ requires slide-caches-first<Base>;
10596
+
10597
+ public:
10598
+ using iterator_category = input_iterator_tag;
10599
+ using iterator_concept = see below;
10600
+ using value_type = decltype(views::counted(current_, n_));
10601
+ using difference_type = range_difference_t<Base>;
10602
+
10603
+ iterator() = default;
10604
+ constexpr iterator(iterator<!Const> i)
10605
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
10606
+
10607
+ constexpr auto operator*() const;
10608
+ constexpr iterator& operator++();
10609
+ constexpr iterator operator++(int);
10610
+
10611
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
10612
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
10613
+
10614
+ constexpr iterator& operator+=(difference_type x)
10615
+ requires random_access_range<Base>;
10616
+ constexpr iterator& operator-=(difference_type x)
10617
+ requires random_access_range<Base>;
10618
+
10619
+ constexpr auto operator[](difference_type n) const
10620
+ requires random_access_range<Base>;
10621
+
10622
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
10623
+
10624
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
10625
+ requires random_access_range<Base>;
10626
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
10627
+ requires random_access_range<Base>;
10628
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
10629
+ requires random_access_range<Base>;
10630
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
10631
+ requires random_access_range<Base>;
10632
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
10633
+ requires random_access_range<Base> &&
10634
+ three_way_comparable<iterator_t<Base>>;
10635
+
10636
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
10637
+ requires random_access_range<Base>;
10638
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
10639
+ requires random_access_range<Base>;
10640
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
10641
+ requires random_access_range<Base>;
10642
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
10643
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
10644
+ };
10645
+ }
10646
+ ```
10647
+
10648
+ `iterator::iterator_concept` is defined as follows:
10649
+
10650
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
10651
+ denotes `random_access_iterator_tag`.
10652
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
10653
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
10654
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
10655
+
10656
+ If the invocation of any non-const member function of *`iterator`* exits
10657
+ via an exception, the *`iterator`* acquires a singular value.
10658
+
10659
+ ``` cpp
10660
+ constexpr iterator(iterator_t<Base> current, range_difference_t<Base> n)
10661
+ requires (!slide-caches-first<Base>);
10662
+ ```
10663
+
10664
+ *Effects:* Initializes *current\_* with `current` and *n\_* with `n`.
10665
+
10666
+ ``` cpp
10667
+ constexpr iterator(iterator_t<Base> current, iterator_t<Base> last_ele,
10668
+ range_difference_t<Base> n)
10669
+ requires slide-caches-first<Base>;
10670
+ ```
10671
+
10672
+ *Effects:* Initializes *current\_* with `current`, *last_ele\_* with
10673
+ `last_ele`, and *n\_* with `n`.
10674
+
10675
+ ``` cpp
10676
+ constexpr iterator(iterator<!Const> i)
10677
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
10678
+ ```
10679
+
10680
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`
10681
+ and *n\_* with `i.`*`n_`*.
10682
+
10683
+ [*Note 1*: *`iterator`*`<true>` can only be formed when *Base* models
10684
+ `slide-caches-nothing`, in which case *last_ele\_* is not
10685
+ present. — *end note*]
10686
+
10687
+ ``` cpp
10688
+ constexpr auto operator*() const;
10689
+ ```
10690
+
10691
+ *Returns:* `views::counted(`*`current_`*`, `*`n_`*`)`.
10692
+
10693
+ ``` cpp
10694
+ constexpr iterator& operator++();
10695
+ ```
10696
+
10697
+ *Preconditions:* *current\_* and *last_ele\_* (if present) are
10698
+ incrementable.
10699
+
10700
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
10701
+ `ranges::next(i)`, where `i` is the value of that data member before the
10702
+ call.
10703
+
10704
+ *Returns:* `*this`.
10705
+
10706
+ ``` cpp
10707
+ constexpr iterator operator++(int);
10708
+ ```
10709
+
10710
+ *Effects:* Equivalent to:
10711
+
10712
+ ``` cpp
10713
+ auto tmp = *this;
10714
+ ++*this;
10715
+ return tmp;
10716
+ ```
10717
+
10718
+ ``` cpp
10719
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
10720
+ ```
10721
+
10722
+ *Preconditions:* *current\_* and *last_ele\_* (if present) are
10723
+ decrementable.
10724
+
10725
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
10726
+ `ranges::prev(i)`, where `i` is the value of that data member before the
10727
+ call.
10728
+
10729
+ *Returns:* `*this`.
10730
+
10731
+ ``` cpp
10732
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
10733
+ ```
10734
+
10735
+ *Effects:* Equivalent to:
10736
+
10737
+ ``` cpp
10738
+ auto tmp = *this;
10739
+ --*this;
10740
+ return tmp;
10741
+ ```
10742
+
10743
+ ``` cpp
10744
+ constexpr iterator& operator+=(difference_type x)
10745
+ requires random_access_range<Base>;
10746
+ ```
10747
+
10748
+ *Preconditions:* *`current_`*` + x` and *`last_ele_`*` + x` (if
10749
+ *last_ele\_* is present) have well-defined behavior.
10750
+
10751
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
10752
+ `i + x`, where `i` is the value of that data member before the call.
10753
+
10754
+ *Returns:* `*this`.
10755
+
10756
+ ``` cpp
10757
+ constexpr iterator& operator-=(difference_type x)
10758
+ requires random_access_range<Base>;
10759
+ ```
10760
+
10761
+ *Preconditions:* *`current_`*` - x` and *`last_ele_`*` - x` (if
10762
+ *last_ele\_* is present) have well-defined behavior.
10763
+
10764
+ *Ensures:* *current\_* and *last_ele\_* (if present) are each equal to
10765
+ `i - x`, where `i` is the value of that data member before the call.
10766
+
10767
+ *Returns:* `*this`.
10768
+
10769
+ ``` cpp
10770
+ constexpr auto operator[](difference_type n) const
10771
+ requires random_access_range<Base>;
10772
+ ```
10773
+
10774
+ *Effects:* Equivalent to:
10775
+ `return views::counted(`*`current_`*` + n, `*`n_`*`);`
10776
+
10777
+ ``` cpp
10778
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
10779
+ ```
10780
+
10781
+ *Returns:* If *last_ele\_* is present,
10782
+ `x.`*`last_ele_`*` == y.`*`last_ele_`*; otherwise,
10783
+ `x.`*`current_`*` == y.`*`current_`*.
10784
+
10785
+ ``` cpp
10786
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
10787
+ requires random_access_range<Base>;
10788
+ ```
10789
+
10790
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
10791
+
10792
+ ``` cpp
10793
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
10794
+ requires random_access_range<Base>;
10795
+ ```
10796
+
10797
+ *Effects:* Equivalent to: `return y < x;`
10798
+
10799
+ ``` cpp
10800
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
10801
+ requires random_access_range<Base>;
10802
+ ```
10803
+
10804
+ *Effects:* Equivalent to: `return !(y < x);`
10805
+
10806
+ ``` cpp
10807
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
10808
+ requires random_access_range<Base>;
10809
+ ```
10810
+
10811
+ *Effects:* Equivalent to: `return !(x < y);`
10812
+
10813
+ ``` cpp
10814
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
10815
+ requires random_access_range<Base> &&
10816
+ three_way_comparable<iterator_t<Base>>;
10817
+ ```
10818
+
10819
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
10820
+
10821
+ ``` cpp
10822
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
10823
+ requires random_access_range<Base>;
10824
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
10825
+ requires random_access_range<Base>;
10826
+ ```
10827
+
10828
+ *Effects:* Equivalent to:
10829
+
10830
+ ``` cpp
10831
+ auto r = i;
10832
+ r += n;
10833
+ return r;
10834
+ ```
10835
+
10836
+ ``` cpp
10837
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
10838
+ requires random_access_range<Base>;
10839
+ ```
10840
+
10841
+ *Effects:* Equivalent to:
10842
+
10843
+ ``` cpp
10844
+ auto r = i;
10845
+ r -= n;
10846
+ return r;
10847
+ ```
10848
+
10849
+ ``` cpp
10850
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
10851
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
10852
+ ```
10853
+
10854
+ *Returns:* If *last_ele\_* is present,
10855
+ `x.`*`last_ele_`*` - y.`*`last_ele_`*; otherwise,
10856
+ `x.`*`current_`*` - y.`*`current_`*.
10857
+
10858
+ #### Class `slide_view::sentinel` <a id="range.slide.sentinel">[[range.slide.sentinel]]</a>
10859
+
10860
+ ``` cpp
10861
+ namespace std::ranges {
10862
+ template<forward_range V>
10863
+ requires view<V>
10864
+ class slide_view<V>::sentinel {
10865
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
10866
+ constexpr explicit sentinel(sentinel_t<V> end); // exposition only
10867
+
10868
+ public:
10869
+ sentinel() = default;
10870
+
10871
+ friend constexpr bool operator==(const iterator<false>& x, const sentinel& y);
10872
+
10873
+ friend constexpr range_difference_t<V>
10874
+ operator-(const iterator<false>& x, const sentinel& y)
10875
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10876
+
10877
+ friend constexpr range_difference_t<V>
10878
+ operator-(const sentinel& y, const iterator<false>& x)
10879
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10880
+ };
10881
+ }
10882
+ ```
10883
+
10884
+ [*Note 1*: *`sentinel`* is used only when `slide-caches-first<V>` is
10885
+ `true`. — *end note*]
10886
+
10887
+ ``` cpp
10888
+ constexpr explicit sentinel(sentinel_t<V> end);
10889
+ ```
10890
+
10891
+ *Effects:* Initializes *end\_* with `end`.
10892
+
10893
+ ``` cpp
10894
+ friend constexpr bool operator==(const iterator<false>& x, const sentinel& y);
10895
+ ```
10896
+
10897
+ *Returns:* `x.`*`last_ele_`*` == y.`*`end_`*.
10898
+
10899
+ ``` cpp
10900
+ friend constexpr range_difference_t<V>
10901
+ operator-(const iterator<false>& x, const sentinel& y)
10902
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10903
+ ```
10904
+
10905
+ *Returns:* `x.`*`last_ele_`*` - y.`*`end_`*.
10906
+
10907
+ ``` cpp
10908
+ friend constexpr range_difference_t<V>
10909
+ operator-(const sentinel& y, const iterator<false>& x)
10910
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10911
+ ```
10912
+
10913
+ *Returns:* `y.`*`end_`*` - x.`*`last_ele_`*.
10914
+
10915
+ ### Chunk by view <a id="range.chunk.by">[[range.chunk.by]]</a>
10916
+
10917
+ #### Overview <a id="range.chunk.by.overview">[[range.chunk.by.overview]]</a>
10918
+
10919
+ `chunk_by_view` takes a view and a predicate, and splits the view into
10920
+ `subrange`s between each pair of adjacent elements for which the
10921
+ predicate returns `false`.
10922
+
10923
+ The name `views::chunk_by` denotes a range adaptor object
10924
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
10925
+ expression `views::chunk_by(E, F)` is expression-equivalent to
10926
+ `chunk_by_view(E, F)`.
10927
+
10928
+ [*Example 1*:
10929
+
10930
+ ``` cpp
10931
+ vector v = {1, 2, 2, 3, 0, 4, 5, 2};
10932
+
10933
+ for (auto r : v | views::chunk_by(ranges::less_equal{})) {
10934
+ cout << '[';
10935
+ auto sep = "";
10936
+ for (auto i : r) {
10937
+ cout << sep << i;
10938
+ sep = ", ";
10939
+ }
10940
+ cout << "] ";
10941
+ }
10942
+ // The above prints [1, 2, 2, 3] [0, 4, 5] [2]
10943
+ ```
10944
+
10945
+ — *end example*]
10946
+
10947
+ #### Class template `chunk_by_view` <a id="range.chunk.by.view">[[range.chunk.by.view]]</a>
10948
+
10949
+ ``` cpp
10950
+ namespace std::ranges {
10951
+ template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred>
10952
+ requires view<V> && is_object_v<Pred>
10953
+ class chunk_by_view : public view_interface<chunk_by_view<V, Pred>> {
10954
+ V base_ = V(); // exposition only
10955
+ movable-box<Pred> pred_; // exposition only
10956
+
10957
+ // [range.chunk.by.iter], class chunk_by_view::iterator
10958
+ class iterator; // exposition only
10959
+
10960
+ public:
10961
+ chunk_by_view() requires default_initializable<V> && default_initializable<Pred> = default;
10962
+ constexpr explicit chunk_by_view(V base, Pred pred);
10963
+
10964
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
10965
+ constexpr V base() && { return std::move(base_); }
10966
+
10967
+ constexpr const Pred& pred() const;
10968
+
10969
+ constexpr iterator begin();
10970
+ constexpr auto end();
10971
+
10972
+ constexpr iterator_t<V> find-next(iterator_t<V>); // exposition only
10973
+ constexpr iterator_t<V> find-prev(iterator_t<V>) // exposition only
10974
+ requires bidirectional_range<V>;
10975
+ };
10976
+
10977
+ template<class R, class Pred>
10978
+ chunk_by_view(R&&, Pred) -> chunk_by_view<views::all_t<R>, Pred>;
10979
+ }
10980
+ ```
10981
+
10982
+ ``` cpp
10983
+ constexpr explicit chunk_by_view(V base, Pred pred);
10984
+ ```
10985
+
10986
+ *Effects:* Initializes *base\_* with `std::move(base)` and *pred\_* with
10987
+ `std::move(pred)`.
10988
+
10989
+ ``` cpp
10990
+ constexpr const Pred& pred() const;
10991
+ ```
10992
+
10993
+ *Effects:* Equivalent to: `return *`*`pred_`*`;`
10994
+
10995
+ ``` cpp
10996
+ constexpr iterator begin();
10997
+ ```
10998
+
10999
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
11000
+
11001
+ *Returns:*
11002
+ *`iterator`*`(*this, ranges::begin(`*`base_`*`), `*`find-next`*`(ranges::begin(`*`base_`*`)))`.
11003
+
11004
+ *Remarks:* In order to provide the amortized constant-time complexity
11005
+ required by the `range` concept, this function caches the result within
11006
+ the `chunk_by_view` for use on subsequent calls.
11007
+
11008
+ ``` cpp
11009
+ constexpr auto end();
11010
+ ```
11011
+
11012
+ *Effects:* Equivalent to:
11013
+
11014
+ ``` cpp
11015
+ if constexpr (common_range<V>) {
11016
+ return iterator(*this, ranges::end(base_), ranges::end(base_));
11017
+ } else {
11018
+ return default_sentinel;
11019
+ }
11020
+ ```
11021
+
11022
+ ``` cpp
11023
+ constexpr iterator_t<V> find-next(iterator_t<V> current);
11024
+ ```
11025
+
11026
+ *Preconditions:* *`pred_`*`.has_value()` is `true`.
11027
+
11028
+ *Returns:*
11029
+
11030
+ ``` cpp
11031
+ ranges::next(ranges::adjacent_find(current, ranges::end(base_), not_fn(ref(*pred_))),
11032
+ 1, ranges::end(base_))
11033
+ ```
11034
+
11035
+ ``` cpp
11036
+ constexpr iterator_t<V> find-prev(iterator_t<V> current) requires bidirectional_range<V>;
11037
+ ```
11038
+
11039
+ *Preconditions:*
11040
+
11041
+ - `current` is not equal to `ranges::begin(`*`base_`*`)`.
11042
+ - *`pred_`*`.has_value()` is `true`.
11043
+
11044
+ *Returns:* An iterator `i` in the range \[`ranges::begin(`*`base_`*`)`,
11045
+ `current`) such that:
11046
+
11047
+ - `ranges::adjacent_find(i, current, not_fn(ref(*`*`pred_`*`)))` is
11048
+ equal to `current`; and
11049
+ - if `i` is not equal to `ranges::begin(`*`base_`*`)`, then
11050
+ `bool(invoke(*`*`pred_`*`, *ranges::prev(i), *i))` is `false`.
11051
+
11052
+ #### Class `chunk_by_view::iterator` <a id="range.chunk.by.iter">[[range.chunk.by.iter]]</a>
11053
+
11054
+ ``` cpp
11055
+ namespace std::ranges {
11056
+ template<forward_range V, indirect_binary_predicate<iterator_t<V>, iterator_t<V>> Pred>
11057
+ requires view<V> && is_object_v<Pred>
11058
+ class chunk_by_view<V, Pred>::iterator {
11059
+ chunk_by_view* parent_ = nullptr; // exposition only
11060
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only
11061
+ iterator_t<V> next_ = iterator_t<V>(); // exposition only
11062
+
11063
+ constexpr iterator(chunk_by_view& parent, iterator_t<V> current, // exposition only
11064
+ iterator_t<V> next);
11065
+
11066
+ public:
11067
+ using value_type = subrange<iterator_t<V>>;
11068
+ using difference_type = range_difference_t<V>;
11069
+ using iterator_category = input_iterator_tag;
11070
+ using iterator_concept = see below;
11071
+
11072
+ iterator() = default;
11073
+
11074
+ constexpr value_type operator*() const;
11075
+ constexpr iterator& operator++();
11076
+ constexpr iterator operator++(int);
11077
+
11078
+ constexpr iterator& operator--() requires bidirectional_range<V>;
11079
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
11080
+
11081
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
11082
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
11083
+ };
11084
+ }
11085
+ ```
11086
+
11087
+ `iterator::iterator_concept` is defined as follows:
11088
+
11089
+ - If `V` models `bidirectional_range`, then `iterator_concept` denotes
11090
+ `bidirectional_iterator_tag`.
11091
+ - Otherwise, `iterator_concept` denotes `forward_iterator_tag`.
11092
+
11093
+ ``` cpp
11094
+ constexpr iterator(chunk_by_view& parent, iterator_t<V> current, iterator_t<V> next);
11095
+ ```
11096
+
11097
+ *Effects:* Initializes *parent\_* with `addressof(parent)`, *current\_*
11098
+ with `current`, and *next\_* with `next`.
11099
+
11100
+ ``` cpp
11101
+ constexpr value_type operator*() const;
11102
+ ```
11103
+
11104
+ *Preconditions:* *current\_* is not equal to *next\_*.
11105
+
11106
+ *Returns:* `subrange(`*`current_`*`, `*`next_`*`)`.
11107
+
11108
+ ``` cpp
11109
+ constexpr iterator& operator++();
11110
+ ```
11111
+
11112
+ *Preconditions:* *current\_* is not equal to *next\_*.
11113
+
11114
+ *Effects:* Equivalent to:
11115
+
11116
+ ``` cpp
11117
+ current_ = next_;
11118
+ next_ = parent_->find-next(current_);
11119
+ return *this;
11120
+ ```
11121
+
11122
+ ``` cpp
11123
+ constexpr iterator operator++(int);
11124
+ ```
11125
+
11126
+ *Effects:* Equivalent to:
11127
+
11128
+ ``` cpp
11129
+ auto tmp = *this;
11130
+ ++*this;
11131
+ return tmp;
11132
+ ```
11133
+
11134
+ ``` cpp
11135
+ constexpr iterator& operator--() requires bidirectional_range<V>;
11136
+ ```
11137
+
11138
+ *Effects:* Equivalent to:
11139
+
11140
+ ``` cpp
11141
+ next_ = current_;
11142
+ current_ = parent_->find-prev(next_);
11143
+ return *this;
11144
+ ```
11145
+
11146
+ ``` cpp
11147
+ constexpr iterator operator--(int) requires bidirectional_range<V>;
11148
+ ```
11149
+
11150
+ *Effects:* Equivalent to:
11151
+
11152
+ ``` cpp
11153
+ auto tmp = *this;
11154
+ --*this;
11155
+ return tmp;
11156
+ ```
11157
+
11158
+ ``` cpp
11159
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
11160
+ ```
11161
+
11162
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
11163
+
11164
+ ``` cpp
11165
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
11166
+ ```
11167
+
11168
+ *Returns:* `x.`*`current_`*` == x.`*`next_`*.
11169
+
11170
+ ### Stride view <a id="range.stride">[[range.stride]]</a>
11171
+
11172
+ #### Overview <a id="range.stride.overview">[[range.stride.overview]]</a>
11173
+
11174
+ `stride_view` presents a view of an underlying sequence, advancing over
11175
+ n elements at a time, as opposed to the usual single-step succession.
11176
+
11177
+ The name `views::stride` denotes a range adaptor object
11178
+ [[range.adaptor.object]]. Given subexpressions `E` and `N`, the
11179
+ expression `views::stride(E, N)` is expression-equivalent to
11180
+ `stride_view(E, N)`.
11181
+
11182
+ [*Example 1*:
11183
+
11184
+ ``` cpp
11185
+ auto input = views::iota(0, 12) | views::stride(3);
11186
+ ranges::copy(input, ostream_iterator<int>(cout, " ")); // prints 0 3 6 9
11187
+ ranges::copy(input | views::reverse, ostream_iterator<int>(cout, " ")); // prints 9 6 3 0
11188
+ ```
11189
+
11190
+ — *end example*]
11191
+
11192
+ #### Class template `stride_view` <a id="range.stride.view">[[range.stride.view]]</a>
11193
+
11194
+ ``` cpp
11195
+ namespace std::ranges {
11196
+ template<input_range V>
11197
+ requires view<V>
11198
+ class stride_view : public view_interface<stride_view<V>> {
11199
+ V base_; // exposition only
11200
+ range_difference_t<V> stride_; // exposition only
11201
+ // [range.stride.iterator], class template stride_view::iterator
11202
+ template<bool> class iterator; // exposition only
11203
+ public:
11204
+ constexpr explicit stride_view(V base, range_difference_t<V> stride);
11205
+
11206
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
11207
+ constexpr V base() && { return std::move(base_); }
11208
+
11209
+ constexpr range_difference_t<V> stride() const noexcept;
11210
+
11211
+ constexpr auto begin() requires (!simple-view<V>) {
11212
+ return iterator<false>(this, ranges::begin(base_));
11213
+ }
11214
+
11215
+ constexpr auto begin() const requires range<const V> {
11216
+ return iterator<true>(this, ranges::begin(base_));
11217
+ }
11218
+
11219
+ constexpr auto end() requires (!simple-view<V>) {
11220
+ if constexpr (common_range<V> && sized_range<V> && forward_range<V>) {
11221
+ auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_;
11222
+ return iterator<false>(this, ranges::end(base_), missing);
11223
+ } else if constexpr (common_range<V> && !bidirectional_range<V>) {
11224
+ return iterator<false>(this, ranges::end(base_));
11225
+ } else {
11226
+ return default_sentinel;
11227
+ }
11228
+ }
11229
+
11230
+ constexpr auto end() const requires range<const V> {
11231
+ if constexpr (common_range<const V> && sized_range<const V> && forward_range<const V>) {
11232
+ auto missing = (stride_ - ranges::distance(base_) % stride_) % stride_;
11233
+ return iterator<true>(this, ranges::end(base_), missing);
11234
+ } else if constexpr (common_range<const V> && !bidirectional_range<const V>) {
11235
+ return iterator<true>(this, ranges::end(base_));
11236
+ } else {
11237
+ return default_sentinel;
11238
+ }
11239
+ }
11240
+
11241
+ constexpr auto size() requires sized_range<V>;
11242
+ constexpr auto size() const requires sized_range<const V>;
11243
+ };
11244
+
11245
+ template<class R>
11246
+ stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;
11247
+ }
11248
+ ```
11249
+
11250
+ ``` cpp
11251
+ constexpr stride_view(V base, range_difference_t<V> stride);
11252
+ ```
11253
+
11254
+ *Preconditions:* `stride > 0` is `true`.
11255
+
11256
+ *Effects:* Initializes *base\_* with `std::move(base)` and *stride\_*
11257
+ with `stride`.
11258
+
11259
+ ``` cpp
11260
+ constexpr range_difference_t<V> stride() const noexcept;
11261
+ ```
11262
+
11263
+ *Returns:* *stride\_*.
11264
+
11265
+ ``` cpp
11266
+ constexpr auto size() requires sized_range<V>;
11267
+ constexpr auto size() const requires sized_range<const V>;
11268
+ ```
11269
+
11270
+ *Effects:* Equivalent to:
11271
+
11272
+ ``` cpp
11273
+ return to-unsigned-like(div-ceil(ranges::distance(base_), stride_));
11274
+ ```
11275
+
11276
+ #### Class template `stride_view::iterator` <a id="range.stride.iterator">[[range.stride.iterator]]</a>
11277
+
11278
+ ``` cpp
11279
+ namespace std::ranges {
11280
+ template<input_range V>
11281
+ requires view<V>
11282
+ template<bool Const>
11283
+ class stride_view<V>::iterator {
11284
+ using Parent = maybe-const<Const, stride_view>; // exposition only
11285
+ using Base = maybe-const<Const, V>; // exposition only
11286
+
11287
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
11288
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
11289
+ range_difference_t<Base> stride_ = 0; // exposition only
11290
+ range_difference_t<Base> missing_ = 0; // exposition only
11291
+
11292
+ constexpr iterator(Parent* parent, iterator_t<Base> current, // exposition only
11293
+ range_difference_t<Base> missing = 0);
11294
+ public:
11295
+ using difference_type = range_difference_t<Base>;
11296
+ using value_type = range_value_t<Base>;
11297
+ using iterator_concept = see below;
11298
+ using iterator_category = see below; // not always present
11299
+
11300
+ iterator() requires default_initializable<iterator_t<Base>> = default;
11301
+
11302
+ constexpr iterator(iterator<!Const> other)
11303
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
11304
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
11305
+
11306
+ constexpr iterator_t<Base> base() &&;
11307
+ constexpr const iterator_t<Base>& base() const & noexcept;
11308
+
11309
+ constexpr decltype(auto) operator*() const { return *current_; }
11310
+
11311
+ constexpr iterator& operator++();
11312
+ constexpr void operator++(int);
11313
+ constexpr iterator operator++(int) requires forward_range<Base>;
11314
+
11315
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
11316
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
11317
+
11318
+ constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
11319
+ constexpr iterator& operator-=(difference_type n) requires random_access_range<Base>;
11320
+
11321
+ constexpr decltype(auto) operator[](difference_type n) const
11322
+ requires random_access_range<Base>
11323
+ { return *(*this + n); }
11324
+
11325
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
11326
+
11327
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
11328
+ requires equality_comparable<iterator_t<Base>>;
11329
+
11330
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
11331
+ requires random_access_range<Base>;
11332
+
11333
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
11334
+ requires random_access_range<Base>;
11335
+
11336
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
11337
+ requires random_access_range<Base>;
11338
+
11339
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
11340
+ requires random_access_range<Base>;
11341
+
11342
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
11343
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
11344
+
11345
+ friend constexpr iterator operator+(const iterator& x, difference_type n)
11346
+ requires random_access_range<Base>;
11347
+ friend constexpr iterator operator+(difference_type n, const iterator& x)
11348
+ requires random_access_range<Base>;
11349
+ friend constexpr iterator operator-(const iterator& x, difference_type n)
11350
+ requires random_access_range<Base>;
11351
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
11352
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
11353
+
11354
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
11355
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
11356
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
11357
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
11358
+
11359
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
11360
+ noexcept(noexcept(ranges::iter_move(i.current_)));
11361
+
11362
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
11363
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
11364
+ requires indirectly_swappable<iterator_t<Base>>;
11365
+ };
11366
+ }
11367
+ ```
11368
+
11369
+ `iterator::iterator_concept` is defined as follows:
11370
+
11371
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
11372
+ denotes `random_access_iterator_tag`.
11373
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
11374
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
11375
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
11376
+ denotes `forward_iterator_tag`.
11377
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
11378
+
11379
+ The member *typedef-name* `iterator_category` is defined if and only if
11380
+ *`Base`* models `forward_range`. In that case,
11381
+ `iterator::iterator_category` is defined as follows:
11382
+
11383
+ - Let `C` denote the type
11384
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
11385
+ - If `C` models `derived_from<random_access_iterator_tag>`, then
11386
+ `iterator_category` denotes `random_access_iterator_tag`.
11387
+ - Otherwise, `iterator_category` denotes `C`.
11388
+
11389
+ ``` cpp
11390
+ constexpr iterator(Parent* parent, iterator_t<Base> current,
11391
+ range_difference_t<Base> missing = 0);
11392
+ ```
11393
+
11394
+ *Effects:* Initializes *current\_* with `std::move(current)`, *end\_*
11395
+ with `ranges::end(parent->`*`base_`*`)`, *stride\_* with
11396
+ `parent->`*`stride_`*, and *missing\_* with `missing`.
11397
+
11398
+ ``` cpp
11399
+ constexpr iterator(iterator<!Const> i)
11400
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>
11401
+ && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
11402
+ ```
11403
+
11404
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`,
11405
+ *end\_* with `std::move(i.`*`end_`*`)`, *stride\_* with `i.`*`stride_`*,
11406
+ and *missing\_* with `i.`*`missing_`*.
11407
+
11408
+ ``` cpp
11409
+ constexpr iterator_t<Base> base() &&;
11410
+ ```
11411
+
11412
+ *Returns:* `std::move(`*`current_`*`)`.
11413
+
11414
+ ``` cpp
11415
+ constexpr const iterator_t<Base>& base() const & noexcept;
11416
+ ```
11417
+
11418
+ *Returns:* *current\_*.
11419
+
11420
+ ``` cpp
11421
+ constexpr iterator& operator++();
11422
+ ```
11423
+
11424
+ *Preconditions:* *`current_`*` != `*`end_`* is `true`.
11425
+
11426
+ *Effects:* Equivalent to:
11427
+
11428
+ ``` cpp
11429
+ missing_ = ranges::advance(current_, stride_, end_);
11430
+ return *this;
11431
+ ```
11432
+
11433
+ ``` cpp
11434
+ constexpr void operator++(int);
11435
+ ```
11436
+
11437
+ *Effects:* Equivalent to: `++*this;`
11438
+
11439
+ ``` cpp
11440
+ constexpr iterator operator++(int) requires forward_range<Base>;
11441
+ ```
11442
+
11443
+ *Effects:* Equivalent to:
11444
+
11445
+ ``` cpp
11446
+ auto tmp = *this;
11447
+ ++*this;
11448
+ return tmp;
11449
+ ```
11450
+
11451
+ ``` cpp
11452
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
11453
+ ```
11454
+
11455
+ *Effects:* Equivalent to:
11456
+
11457
+ ``` cpp
11458
+ ranges::advance(current_, missing_ - stride_);
11459
+ missing_ = 0;
11460
+ return *this;
11461
+ ```
11462
+
11463
+ ``` cpp
11464
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
11465
+ ```
11466
+
11467
+ *Effects:* Equivalent to:
11468
+
11469
+ ``` cpp
11470
+ auto tmp = *this;
11471
+ --*this;
11472
+ return tmp;
11473
+ ```
11474
+
11475
+ ``` cpp
11476
+ constexpr iterator& operator+=(difference_type n) requires random_access_range<Base>;
11477
+ ```
11478
+
11479
+ *Preconditions:* If `n` is positive,
11480
+ `ranges::distance(`*`current_`*`, `*`end_`*`) > `*`stride_`*` * (n - 1)`
11481
+ is `true`.
11482
+
11483
+ [*Note 1*: If `n` is negative, the *Effects* paragraph implies a
11484
+ precondition. — *end note*]
11485
+
11486
+ *Effects:* Equivalent to:
11487
+
11488
+ ``` cpp
11489
+ if (n > 0) {
11490
+ ranges::advance(current_, stride_ * (n - 1));
11491
+ missing_ = ranges::advance(current_, stride_, end_);
11492
+ } else if (n < 0) {
11493
+ ranges::advance(current_, stride_ * n + missing_);
11494
+ missing_ = 0;
11495
+ }
11496
+ return *this;
11497
+ ```
11498
+
11499
+ ``` cpp
11500
+ constexpr iterator& operator-=(difference_type x)
11501
+ requires random_access_range<Base>;
11502
+ ```
11503
+
11504
+ *Effects:* Equivalent to: `return *this += -x;`
11505
+
11506
+ ``` cpp
11507
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
11508
+ ```
11509
+
11510
+ *Returns:* `x.`*`current_`*` == x.`*`end_`*.
11511
+
11512
+ ``` cpp
11513
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
11514
+ requires equality_comparable<iterator_t<Base>>;
11515
+ ```
11516
+
11517
+ *Returns:* `x.`*`current_`*` == y.`*`current_`*.
11518
+
11519
+ ``` cpp
11520
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
11521
+ requires random_access_range<Base>;
11522
+ ```
11523
+
11524
+ *Returns:* `x.`*`current_`*` < y.`*`current_`*.
11525
+
11526
+ ``` cpp
11527
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
11528
+ requires random_access_range<Base>;
11529
+ ```
11530
+
11531
+ *Effects:* Equivalent to: `return y < x;`
11532
+
11533
+ ``` cpp
11534
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
11535
+ requires random_access_range<Base>;
11536
+ ```
11537
+
11538
+ *Effects:* Equivalent to: `return !(y < x);`
11539
+
11540
+ ``` cpp
11541
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
11542
+ requires random_access_range<Base>;
11543
+ ```
11544
+
11545
+ *Effects:* Equivalent to: `return !(x < y);`
11546
+
11547
+ ``` cpp
11548
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
11549
+ requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
11550
+ ```
11551
+
11552
+ *Returns:* `x.`*`current_`*` <=> y.`*`current_`*.
11553
+
11554
+ ``` cpp
11555
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
11556
+ requires random_access_range<Base>;
11557
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
11558
+ requires random_access_range<Base>;
11559
+ ```
11560
+
11561
+ *Effects:* Equivalent to:
11562
+
11563
+ ``` cpp
11564
+ auto r = i;
11565
+ r += n;
11566
+ return r;
11567
+ ```
11568
+
11569
+ ``` cpp
11570
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
11571
+ requires random_access_range<Base>;
11572
+ ```
11573
+
11574
+ *Effects:* Equivalent to:
11575
+
11576
+ ``` cpp
11577
+ auto r = i;
11578
+ r -= n;
11579
+ return r;
11580
+ ```
11581
+
11582
+ ``` cpp
11583
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
11584
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
11585
+ ```
11586
+
11587
+ *Returns:* Let `N` be `(x.`*`current_`*` - y.`*`current_`*`)`.
11588
+
11589
+ - If *Base* models `forward_range`,
11590
+ `(N + x.`*`missing_`*` - y.`*`missing_`*`) / x.`*`stride_`*.
11591
+ - Otherwise, if `N` is negative, `-`*`div-ceil`*`(-N, x.`*`stride_`*`)`.
11592
+ - Otherwise, *`div-ceil`*`(N, x.`*`stride_`*`)`.
11593
+
11594
+ ``` cpp
11595
+ friend constexpr difference_type operator-(default_sentinel_t y, const iterator& x)
11596
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
11597
+ ```
11598
+
11599
+ *Returns:*
11600
+ *`div-ceil`*`(x.`*`end_`*` - x.`*`current_`*`, x.`*`stride_`*`)`.
11601
+
11602
+ ``` cpp
11603
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t y)
11604
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
11605
+ ```
11606
+
11607
+ *Effects:* Equivalent to: `return -(y - x);`
11608
+
11609
+ ``` cpp
11610
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
11611
+ noexcept(noexcept(ranges::iter_move(i.current_)));
11612
+ ```
11613
+
11614
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
11615
+
11616
+ ``` cpp
11617
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
11618
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
11619
+ requires indirectly_swappable<iterator_t<Base>>;
11620
+ ```
11621
+
11622
+ *Effects:* Equivalent to:
11623
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`);`
11624
+
11625
+ ### Cartesian product view <a id="range.cartesian">[[range.cartesian]]</a>
11626
+
11627
+ #### Overview <a id="range.cartesian.overview">[[range.cartesian.overview]]</a>
11628
+
11629
+ `cartesian_product_view` takes any non-zero number of ranges n and
11630
+ produces a view of tuples calculated by the n-ary cartesian product of
11631
+ the provided ranges.
11632
+
11633
+ The name `views::cartesian_product` denotes a customization point object
11634
+ [[customization.point.object]]. Given a pack of subexpressions `Es`, the
11635
+ expression `views::cartesian_product(Es...)` is expression-equivalent to
11636
+
11637
+ - `views::single(tuple())` if `Es` is an empty pack,
11638
+ - otherwise,
11639
+ `cartesian_product_view<views::all_t<decltype((Es))>...>(Es...)`.
11640
+
11641
+ [*Example 1*:
11642
+
11643
+ ``` cpp
11644
+ vector<int> v { 0, 1, 2 };
11645
+ for (auto&& [a, b, c] : views::cartesian_product(v, v, v)) {
11646
+ cout << a << ' ' << b << ' ' << c << '\n';
11647
+ }
11648
+ // The above prints
11649
+ // 0 0 0
11650
+ // 0 0 1
11651
+ // 0 0 2
11652
+ // 0 1 0
11653
+ // 0 1 1
11654
+ // ...
11655
+ ```
11656
+
11657
+ — *end example*]
11658
+
11659
+ #### Class template `cartesian_product_view` <a id="range.cartesian.view">[[range.cartesian.view]]</a>
11660
+
11661
+ ``` cpp
11662
+ namespace std::ranges {
11663
+ template<bool Const, class First, class... Vs>
11664
+ concept cartesian-product-is-random-access = // exposition only
11665
+ (random_access_range<maybe-const<Const, First>> && ... &&
11666
+ (random_access_range<maybe-const<Const, Vs>>
11667
+ && sized_range<maybe-const<Const, Vs>>));
11668
+
11669
+ template<class R>
11670
+ concept cartesian-product-common-arg = // exposition only
11671
+ common_range<R> || (sized_range<R> && random_access_range<R>);
11672
+
11673
+ template<bool Const, class First, class... Vs>
11674
+ concept cartesian-product-is-bidirectional = // exposition only
11675
+ (bidirectional_range<maybe-const<Const, First>> && ... &&
11676
+ (bidirectional_range<maybe-const<Const, Vs>>
11677
+ && cartesian-product-common-arg<maybe-const<Const, Vs>>));
11678
+
11679
+ template<class First, class... Vs>
11680
+ concept cartesian-product-is-common = // exposition only
11681
+ cartesian-product-common-arg<First>;
11682
+
11683
+ template<class... Vs>
11684
+ concept cartesian-product-is-sized = // exposition only
11685
+ (sized_range<Vs> && ...);
11686
+
11687
+ template<bool Const, template<class> class FirstSent, class First, class... Vs>
11688
+ concept cartesian-is-sized-sentinel = // exposition only
11689
+ (sized_sentinel_for<FirstSent<maybe-const<Const, First>>,
11690
+ iterator_t<maybe-const<Const, First>>> && ...
11691
+ && (sized_range<maybe-const<Const, Vs>>
11692
+ && sized_sentinel_for<iterator_t<maybe-const<Const, Vs>>,
11693
+ iterator_t<maybe-const<Const, Vs>>>));
11694
+
11695
+ template<cartesian-product-common-arg R>
11696
+ constexpr auto cartesian-common-arg-end(R& r) { // exposition only
11697
+ if constexpr (common_range<R>) {
11698
+ return ranges::end(r);
11699
+ } else {
11700
+ return ranges::begin(r) + ranges::distance(r);
11701
+ }
11702
+ }
11703
+
11704
+ template<input_range First, forward_range... Vs>
11705
+ requires (view<First> && ... && view<Vs>)
11706
+ class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {
11707
+ private:
11708
+ tuple<First, Vs...> bases_; // exposition only
11709
+ // [range.cartesian.iterator], class template cartesian_product_view::iterator
11710
+ template<bool Const> class iterator; // exposition only
11711
+
11712
+ public:
11713
+ constexpr cartesian_product_view() = default;
11714
+ constexpr explicit cartesian_product_view(First first_base, Vs... bases);
11715
+
11716
+ constexpr iterator<false> begin()
11717
+ requires (!simple-view<First> || ... || !simple-view<Vs>);
11718
+ constexpr iterator<true> begin() const
11719
+ requires (range<const First> && ... && range<const Vs>);
11720
+
11721
+ constexpr iterator<false> end()
11722
+ requires ((!simple-view<First> || ... || !simple-view<Vs>) &&
11723
+ cartesian-product-is-common<First, Vs...>);
11724
+ constexpr iterator<true> end() const
11725
+ requires cartesian-product-is-common<const First, const Vs...>;
11726
+ constexpr default_sentinel_t end() const noexcept;
11727
+
11728
+ constexpr see below size()
11729
+ requires cartesian-product-is-sized<First, Vs...>;
11730
+ constexpr see below size() const
11731
+ requires cartesian-product-is-sized<const First, const Vs...>;
11732
+ };
11733
+
11734
+ template<class... Vs>
11735
+ cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>;
11736
+ }
11737
+ ```
11738
+
11739
+ ``` cpp
11740
+ constexpr explicit cartesian_product_view(First first_base, Vs... bases);
11741
+ ```
11742
+
11743
+ *Effects:* Initializes *bases\_* with
11744
+ `std::move(first_base), std::move(bases)...`.
11745
+
11746
+ ``` cpp
11747
+ constexpr iterator<false> begin()
11748
+ requires (!simple-view<First> || ... || !simple-view<Vs>);
11749
+ ```
11750
+
11751
+ *Effects:* Equivalent to:
11752
+
11753
+ ``` cpp
11754
+ return iterator<false>(*this, tuple-transform(ranges::begin, bases_));
11755
+ ```
11756
+
11757
+ ``` cpp
11758
+ constexpr iterator<true> begin() const
11759
+ requires (range<const First> && ... && range<const Vs>);
11760
+ ```
11761
+
11762
+ *Effects:* Equivalent to:
11763
+
11764
+ ``` cpp
11765
+ return iterator<true>(*this, tuple-transform(ranges::begin, bases_));
11766
+ ```
11767
+
11768
+ ``` cpp
11769
+ constexpr iterator<false> end()
11770
+ requires ((!simple-view<First> || ... || !simple-view<Vs>)
11771
+ && cartesian-product-is-common<First, Vs...>);
11772
+ constexpr iterator<true> end() const
11773
+ requires cartesian-product-is-common<const First, const Vs...>;
11774
+ ```
11775
+
11776
+ Let:
11777
+
11778
+ - *is-const* be `true` for the const-qualified overload, and `false`
11779
+ otherwise;
11780
+ - *is-empty* be `true` if the expression `ranges::empty(rng)` is `true`
11781
+ for any `rng` among the underlying ranges except the first one and
11782
+ `false` otherwise; and
11783
+ - *`begin-or-first-end`*`(rng)` be expression-equivalent to
11784
+ *`is-empty`*` ? ranges::begin(rng) : `*`cartesian-common-arg-end`*`(rng)`
11785
+ if `rng` is the first underlying range and `ranges::begin(rng)`
11786
+ otherwise.
11787
+
11788
+ *Effects:* Equivalent to:
11789
+
11790
+ ``` cpp
11791
+ iterator<is-const> it(*this, tuple-transform(
11792
+ [](auto& rng){ return begin-or-first-end(rng); }, bases_));
11793
+ return it;
11794
+ ```
11795
+
11796
+ ``` cpp
11797
+ constexpr default_sentinel_t end() const noexcept;
11798
+ ```
11799
+
11800
+ *Returns:* `default_sentinel`.
11801
+
11802
+ ``` cpp
11803
+ constexpr see below size()
11804
+ requires cartesian-product-is-sized<First, Vs...>;
11805
+ constexpr see below size() const
11806
+ requires cartesian-product-is-sized<const First, const Vs...>;
11807
+ ```
11808
+
11809
+ The return type is an *implementation-defined* unsigned-integer-like
11810
+ type.
11811
+
11812
+ *Recommended practice:* The return type should be the smallest
11813
+ unsigned-integer-like type that is sufficiently wide to store the
11814
+ product of the maximum sizes of all the underlying ranges, if such a
11815
+ type exists.
11816
+
11817
+ Let p be the product of the sizes of all the ranges in *bases\_*.
11818
+
11819
+ *Preconditions:* p can be represented by the return type.
11820
+
11821
+ *Returns:* p.
11822
+
11823
+ #### Class template `cartesian_product_view::iterator` <a id="range.cartesian.iterator">[[range.cartesian.iterator]]</a>
11824
+
11825
+ ``` cpp
11826
+ namespace std::ranges {
11827
+ template<input_range First, forward_range... Vs>
11828
+ requires (view<First> && ... && view<Vs>)
11829
+ template<bool Const>
11830
+ class cartesian_product_view<First, Vs...>::iterator {
11831
+ public:
11832
+ using iterator_category = input_iterator_tag;
11833
+ using iterator_concept = see below;
11834
+ using value_type = tuple<range_value_t<maybe-const<Const, First>>,
11835
+ range_value_t<maybe-const<Const, Vs>>...>;
11836
+ using reference = tuple<range_reference_t<maybe-const<Const, First>>,
11837
+ range_reference_t<maybe-const<Const, Vs>>...>;
11838
+ using difference_type = see below;
11839
+
11840
+ iterator() = default;
11841
+
11842
+ constexpr iterator(iterator<!Const> i) requires Const &&
11843
+ (convertible_to<iterator_t<First>, iterator_t<const First>> &&
11844
+ ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>);
11845
+
11846
+ constexpr auto operator*() const;
11847
+ constexpr iterator& operator++();
11848
+ constexpr void operator++(int);
11849
+ constexpr iterator operator++(int) requires forward_range<maybe-const<Const, First>>;
11850
+
11851
+ constexpr iterator& operator--()
11852
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
11853
+ constexpr iterator operator--(int)
11854
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
11855
+
11856
+ constexpr iterator& operator+=(difference_type x)
11857
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
11858
+ constexpr iterator& operator-=(difference_type x)
11859
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
11860
+
11861
+ constexpr reference operator[](difference_type n) const
11862
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
11863
+
11864
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
11865
+ requires equality_comparable<iterator_t<maybe-const<Const, First>>>;
11866
+
11867
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
11868
+
11869
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
11870
+ requires all-random-access<Const, First, Vs...>;
11871
+
11872
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
11873
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
11874
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
11875
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
11876
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
11877
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
11878
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
11879
+ requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
11880
+
11881
+ friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
11882
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
11883
+ friend constexpr difference_type operator-(default_sentinel_t, const iterator& i)
11884
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
11885
+
11886
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
11887
+
11888
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
11889
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, First>>> && ... &&
11890
+ indirectly_swappable<iterator_t<maybe-const<Const, Vs>>>);
11891
+
11892
+ private:
11893
+ using Parent = maybe-const<Const, cartesian_product_view>; // exposition only
11894
+ Parent* parent_ = nullptr; // exposition only
11895
+ tuple<iterator_t<maybe-const<Const, First>>,
11896
+ iterator_t<maybe-const<Const, Vs>>...> current_; // exposition only
11897
+
11898
+ template<size_t N = sizeof...(Vs)>
11899
+ constexpr void next(); // exposition only
11900
+
11901
+ template<size_t N = sizeof...(Vs)>
11902
+ constexpr void prev(); // exposition only
11903
+
11904
+ template<class Tuple>
11905
+ constexpr difference_type distance-from(const Tuple& t) const; // exposition only
11906
+
11907
+ constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>,
11908
+ iterator_t<maybe-const<Const, Vs>>...> current); // exposition only
11909
+ };
11910
+ }
11911
+ ```
11912
+
11913
+ `iterator::iterator_concept` is defined as follows:
11914
+
11915
+ - If `cartesian-product-is-random-access<Const, First, Vs...>` is
11916
+ modeled, then `iterator_concept` denotes `random_access_iterator_tag`.
11917
+ - Otherwise, if
11918
+ `cartesian-product-is-bidirectional<Const, First, Vs...>` is modeled,
11919
+ then `iterator_concept` denotes `bidirectional_iterator_tag`.
11920
+ - Otherwise, if `maybe-const<Const, First>` models `forward_range`, then
11921
+ `iterator_concept` denotes `forward_iterator_tag`.
11922
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
11923
+
11924
+ `iterator::difference_type` is an *implementation-defined*
11925
+ signed-integer-like type.
11926
+
11927
+ *Recommended practice:* `iterator::difference_type` should be the
11928
+ smallest signed-integer-like type that is sufficiently wide to store the
11929
+ product of the maximum sizes of all underlying ranges if such a type
11930
+ exists.
11931
+
11932
+ ``` cpp
11933
+ template<size_t N = sizeof...(Vs)>
11934
+ constexpr void next();
11935
+ ```
11936
+
11937
+ *Effects:* Equivalent to:
11938
+
11939
+ ``` cpp
11940
+ auto& it = std::get<N>(current_);
11941
+ ++it;
11942
+ if constexpr (N > 0) {
11943
+ if (it == ranges::end(std::get<N>(parent_->bases_))) {
11944
+ it = ranges::begin(std::get<N>(parent_->bases_));
11945
+ next<N - 1>();
11946
+ }
11947
+ }
11948
+ ```
11949
+
11950
+ ``` cpp
11951
+ template<size_t N = sizeof...(Vs)>
11952
+ constexpr void prev();
11953
+ ```
11954
+
11955
+ *Effects:* Equivalent to:
11956
+
11957
+ ``` cpp
11958
+ auto& it = std::get<N>(current_);
11959
+ if constexpr (N > 0) {
11960
+ if (it == ranges::begin(std::get<N>(parent_->bases_))) {
11961
+ it = cartesian-common-arg-end(std::get<N>(parent_->bases_));
11962
+ prev<N - 1>();
11963
+ }
11964
+ }
11965
+ --it;
11966
+ ```
11967
+
11968
+ ``` cpp
11969
+ template<class Tuple>
11970
+ constexpr difference_type distance-from(const Tuple& t) const;
11971
+ ```
11972
+
11973
+ Let:
11974
+
11975
+ - scaled-size(N) be the product of
11976
+ `static_cast<difference_type>(ranges::size(std::get<`N`>(`*`parent_`*`->`*`bases_`*`)))`
11977
+ and scaled-size(N+1) if N ≤ `sizeof...(Vs)`, otherwise
11978
+ `static_cast<difference_type>(1)`;
11979
+ - scaled-distance(N) be the product of
11980
+ `static_cast<difference_type>(std::get<`N`>(`*`current_`*`) - std::get<`N`>(t))`
11981
+ and scaled-size(N+1); and
11982
+ - *scaled-sum* be the sum of scaled-distance(N) for every integer
11983
+ 0 ≤ N ≤ `sizeof...(Vs)`.
11984
+
11985
+ *Preconditions:* *scaled-sum* can be represented by `difference_type`.
11986
+
11987
+ *Returns:* *scaled-sum*.
11988
+
11989
+ ``` cpp
11990
+ constexpr iterator(Parent& parent, tuple<iterator_t<maybe-const<Const, First>>,
11991
+ iterator_t<maybe-const<Const, Vs>>...> current);
11992
+ ```
11993
+
11994
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and
11995
+ *current\_* with `std::move(current)`.
11996
+
11997
+ ``` cpp
11998
+ constexpr iterator(iterator<!Const> i) requires Const &&
11999
+ (convertible_to<iterator_t<First>, iterator_t<const First>> &&
12000
+ ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>);
12001
+ ```
12002
+
12003
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *current\_*
12004
+ with `std::move(i.`*`current_`*`)`.
12005
+
12006
+ ``` cpp
12007
+ constexpr auto operator*() const;
12008
+ ```
12009
+
12010
+ *Effects:* Equivalent to:
12011
+
12012
+ ``` cpp
12013
+ return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
12014
+ ```
12015
+
12016
+ ``` cpp
12017
+ constexpr iterator& operator++();
12018
+ ```
12019
+
12020
+ *Effects:* Equivalent to:
12021
+
12022
+ ``` cpp
12023
+ next();
12024
+ return *this;
12025
+ ```
12026
+
12027
+ ``` cpp
12028
+ constexpr void operator++(int);
12029
+ ```
12030
+
12031
+ *Effects:* Equivalent to `++*this`.
12032
+
12033
+ ``` cpp
12034
+ constexpr iterator operator++(int) requires forward_range<maybe-const<Const, First>>;
12035
+ ```
12036
+
12037
+ *Effects:* Equivalent to:
12038
+
12039
+ ``` cpp
12040
+ auto tmp = *this;
12041
+ ++*this;
12042
+ return tmp;
12043
+ ```
12044
+
12045
+ ``` cpp
12046
+ constexpr iterator& operator--()
12047
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
12048
+ ```
12049
+
12050
+ *Effects:* Equivalent to:
12051
+
12052
+ ``` cpp
12053
+ prev();
12054
+ return *this;
12055
+ ```
12056
+
12057
+ ``` cpp
12058
+ constexpr iterator operator--(int)
12059
+ requires cartesian-product-is-bidirectional<Const, First, Vs...>;
12060
+ ```
12061
+
12062
+ *Effects:* Equivalent to:
12063
+
12064
+ ``` cpp
12065
+ auto tmp = *this;
12066
+ --*this;
12067
+ return tmp;
12068
+ ```
12069
+
12070
+ ``` cpp
12071
+ constexpr iterator& operator+=(difference_type x)
12072
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
12073
+ ```
12074
+
12075
+ Let `orig` be the value of `*this` before the call.
12076
+
12077
+ Let `ret` be:
12078
+
12079
+ - If `x > 0`, the value of `*this` had *next* been called `x` times.
12080
+ - Otherwise, if `x < 0`, the value of `*this` had *prev* been called
12081
+ `-x` times.
12082
+ - Otherwise, `orig`.
12083
+
12084
+ *Preconditions:* `x` is in the range
12085
+ $[\texttt{ranges::distance(*this, ranges::begin(*\textit{parent_}))},$
12086
+ $\texttt{ranges::distance(*this, ranges::end(*\textit{parent_}))}]$.
12087
+
12088
+ *Effects:* Sets the value of `*this` to `ret`.
12089
+
12090
+ *Returns:* `*this`.
12091
+
12092
+ *Complexity:* Constant.
12093
+
12094
+ ``` cpp
12095
+ constexpr iterator& operator-=(difference_type x)
12096
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
12097
+ ```
12098
+
12099
+ *Effects:* Equivalent to:
12100
+
12101
+ ``` cpp
12102
+ *this += -x;
12103
+ return *this;
12104
+ ```
12105
+
12106
+ ``` cpp
12107
+ constexpr reference operator[](difference_type n) const
12108
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
12109
+ ```
12110
+
12111
+ *Effects:* Equivalent to: `return *((*this) + n);`
12112
+
12113
+ ``` cpp
12114
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
12115
+ requires equality_comparable<iterator_t<maybe-const<Const, First>>>;
12116
+ ```
12117
+
12118
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
12119
+
12120
+ ``` cpp
12121
+ friend constexpr bool operator==(const iterator& x, default_sentinel_t);
12122
+ ```
12123
+
12124
+ *Returns:* `true` if
12125
+ `std::get<`i`>(x.`*`current_`*`) == ranges::end(std::get<`i`>(x.`*`parent_`*`->`*`bases_`*`))`
12126
+ is `true` for any integer 0 ≤ i ≤ `sizeof...(Vs)`; otherwise, `false`.
12127
+
12128
+ ``` cpp
12129
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
12130
+ requires all-random-access<Const, First, Vs...>;
12131
+ ```
12132
+
12133
+ *Effects:* Equivalent to:
12134
+ `return x.`*`current_`*` <=> y.`*`current_`*`;`
12135
+
12136
+ ``` cpp
12137
+ friend constexpr iterator operator+(const iterator& x, difference_type y)
12138
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
12139
+ ```
12140
+
12141
+ *Effects:* Equivalent to: `return `*`iterator`*`(x) += y;`
12142
+
12143
+ ``` cpp
12144
+ friend constexpr iterator operator+(difference_type x, const iterator& y)
12145
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
12146
+ ```
12147
+
12148
+ *Effects:* Equivalent to: `return y + x;`
12149
+
12150
+ ``` cpp
12151
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
12152
+ requires cartesian-product-is-random-access<Const, First, Vs...>;
12153
+ ```
12154
+
12155
+ *Effects:* Equivalent to: `return `*`iterator`*`(x) -= y;`
12156
+
12157
+ ``` cpp
12158
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
12159
+ requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
12160
+ ```
12161
+
12162
+ *Effects:* Equivalent to:
12163
+ `return x.`*`distance-from`*`(y.`*`current_`*`);`
12164
+
12165
+ ``` cpp
12166
+ friend constexpr difference_type operator-(const iterator& i, default_sentinel_t)
12167
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
12168
+ ```
12169
+
12170
+ Let *end-tuple* be an object of a type that is a specialization of
12171
+ `tuple`, such that:
12172
+
12173
+ - `std::get<0>(`*`end-tuple`*`)` has the same value as
12174
+ `ranges::end(std::get<0>(i.`*`parent_`*`->`*`bases_`*`))`;
12175
+ - `std::get<`N`>(`*`end-tuple`*`)` has the same value as
12176
+ `ranges::begin(std::get<`N`>(i.`*`parent_`*`->`*`bases_`*`))` for
12177
+ every integer 1 ≤ N ≤ `sizeof...(Vs)`.
12178
+
12179
+ *Effects:* Equivalent to:
12180
+ `return i.`*`distance-from`*`(`*`end-tuple`*`);`
12181
+
12182
+ ``` cpp
12183
+ friend constexpr difference_type operator-(default_sentinel_t s, const iterator& i)
12184
+ requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
12185
+ ```
12186
+
12187
+ *Effects:* Equivalent to: `return -(i - s);`
12188
+
12189
+ ``` cpp
12190
+ friend constexpr auto iter_move(const iterator& i) noexcept(see below);
12191
+ ```
12192
+
12193
+ *Effects:* Equivalent to:
12194
+ `return `*`tuple-transform`*`(ranges::iter_move, i.`*`current_`*`);`
12195
+
12196
+ *Remarks:* The exception specification is equivalent to the logical of
12197
+ the following expressions:
12198
+
12199
+ - `noexcept(ranges::iter_move(std::get<`N`>(i.`*`current_`*`)))` for
12200
+ every integer 0 ≤ N ≤ `sizeof...(Vs)`,
12201
+ - `is_nothrow_move_constructible_v<range_rvalue_reference_t<`*`maybe-const`*`<Const, T>>>`
12202
+ for every type `T` in `First, Vs...`.
12203
+
12204
+ ``` cpp
12205
+ friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
12206
+ requires (indirectly_swappable<iterator_t<maybe-const<Const, First>>> && ... &&
12207
+ indirectly_swappable<iterator_t<maybe-const<Const, Vs>>>);
12208
+ ```
12209
+
12210
+ *Effects:* For every integer 0 ≤ i ≤ `sizeof...(Vs)`, performs:
12211
+
12212
+ ``` cpp
12213
+ ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
12214
+ ```
12215
+
12216
+ *Remarks:* The exception specification is equivalent to the logical of
12217
+ the following expressions:
12218
+
12219
+ - `noexcept(ranges::iter_swap(std::get<`i`>(l.`*`current_`*`), std::get<`i`>(r.`*`current_`*`)))`
12220
+ for every integer 0 ≤ i ≤ `sizeof...(Vs)`.
12221
+
12222
+ ## Range generators <a id="coro.generator">[[coro.generator]]</a>
12223
+
12224
+ ### Overview <a id="coroutine.generator.overview">[[coroutine.generator.overview]]</a>
12225
+
12226
+ Class template `generator` presents a view of the elements yielded by
12227
+ the evaluation of a coroutine.
12228
+
12229
+ A `generator` generates a sequence of elements by repeatedly resuming
12230
+ the coroutine from which it was returned. Elements of the sequence are
12231
+ produced by the coroutine each time a `co_yield` statement is evaluated.
12232
+ When the `co_yield` statement is of the form `co_yield elements_of(r)`,
12233
+ each element of the range `r` is successively produced as an element of
12234
+ the sequence.
12235
+
12236
+ [*Example 1*:
12237
+
12238
+ ``` cpp
12239
+ generator<int> ints(int start = 0) {
12240
+ while (true)
12241
+ co_yield start++;
12242
+ }
12243
+
12244
+ void f() {
12245
+ for (auto i : ints() | views::take(3))
12246
+ cout << i << ' '; // prints 0 1 2
12247
+ }
12248
+ ```
12249
+
12250
+ — *end example*]
12251
+
12252
+ ### Header `<generator>` synopsis <a id="generator.syn">[[generator.syn]]</a>
12253
+
12254
+ ``` cpp
12255
+ namespace std {
12256
+ // [coro.generator.class], class template generator
12257
+ template<class Ref, class V = void, class Allocator = void>
12258
+ class generator;
12259
+
12260
+ namespace pmr {
12261
+ template<class R, class V = void>
12262
+ using generator = std::generator<R, V, polymorphic_allocator<>>;
12263
+ }
12264
+ }
12265
+ ```
12266
+
12267
+ ### Class template `generator` <a id="coro.generator.class">[[coro.generator.class]]</a>
12268
+
12269
+ ``` cpp
12270
+ namespace std {
12271
+ template<class Ref, class V = void, class Allocator = void>
12272
+ class generator : public ranges::view_interface<generator<Ref, V, Allocator>> {
12273
+ private:
12274
+ using value = conditional_t<is_void_v<V>, remove_cvref_t<Ref>, V>; // exposition only
12275
+ using reference = conditional_t<is_void_v<V>, Ref&&, Ref>; // exposition only
12276
+
12277
+ // [coro.generator.iterator], class generator::iterator
12278
+ class iterator; // exposition only
12279
+
12280
+ public:
12281
+ using yielded =
12282
+ conditional_t<is_reference_v<reference>, reference, const reference&>;
12283
+
12284
+ // [coro.generator.promise], class generator::promise_type
12285
+ class promise_type;
12286
+
12287
+ generator(const generator&) = delete;
12288
+ generator(generator&& other) noexcept;
12289
+
12290
+ ~generator();
12291
+
12292
+ generator& operator=(generator other) noexcept;
12293
+
12294
+ iterator begin();
12295
+ default_sentinel_t end() const noexcept;
12296
+
12297
+ private:
12298
+ coroutine_handle<promise_type> coroutine_ = nullptr; // exposition only
12299
+ unique_ptr<stack<coroutine_handle<>>> active_; // exposition only
12300
+ };
12301
+ }
12302
+ ```
12303
+
12304
+ *Mandates:*
12305
+
12306
+ - If `Allocator` is not `void`, `allocator_traits<Allocator>::pointer`
12307
+ is a pointer type.
12308
+ - *`value`* is a cv-unqualified object type.
12309
+ - *`reference`* is either a reference type, or a cv-unqualified object
12310
+ type that models `copy_constructible`.
12311
+ - Let `RRef` denote `remove_reference_t<reference>&&` if *`reference`*
12312
+ is a reference type, and *`reference`* otherwise. Each of:
12313
+ - `common_reference_with<reference&&, value&>`,
12314
+ - `common_reference_with<reference&&, RRef&&>`, and
12315
+ - `\texttt{common_reference_with}<RRef&&, const \exposid{value}&>`
12316
+
12317
+ is modeled.
12318
+ \[*Note 1*: These requirements ensure the exposition-only *`iterator`*
12319
+ type can model `indirectly_readable` and thus
12320
+ `input_iterator`. — *end note*]
12321
+
12322
+ If `Allocator` is not `void`, it shall meet the *Cpp17Allocator*
12323
+ requirements.
12324
+
12325
+ Specializations of `generator` model `view` and `input_range`.
12326
+
12327
+ The behavior of a program that adds a specialization for `generator` is
12328
+ undefined.
12329
+
12330
+ ### Members <a id="coro.generator.members">[[coro.generator.members]]</a>
12331
+
12332
+ ``` cpp
12333
+ generator(generator&& other) noexcept;
12334
+ ```
12335
+
12336
+ *Effects:* Initializes *coroutine\_* with
12337
+ `exchange(other.`*`coroutine_`*`, {})` and *active\_* with
12338
+ `exchange(other.active_, nullptr)`.
12339
+
12340
+ [*Note 1*: Iterators previously obtained from `other` are not
12341
+ invalidated; they become iterators into `*this`. — *end note*]
12342
+
12343
+ ``` cpp
12344
+ ~generator();
12345
+ ```
12346
+
12347
+ *Effects:* Equivalent to:
12348
+
12349
+ ``` cpp
12350
+ if (coroutine_) {
12351
+ coroutine_.destroy();
12352
+ }
12353
+ ```
12354
+
12355
+ [*Note 2*: Ownership of recursively yielded generators is held in
12356
+ awaitable objects in the coroutine frame of the yielding generator, so
12357
+ destroying the root generator effectively destroys the entire stack of
12358
+ yielded generators. — *end note*]
12359
+
12360
+ ``` cpp
12361
+ generator& operator=(generator other) noexcept;
12362
+ ```
12363
+
12364
+ *Effects:* Equivalent to:
12365
+
12366
+ ``` cpp
12367
+ swap(coroutine_, other.coroutine_);
12368
+ swap(active_, other.active_);
12369
+ ```
12370
+
12371
+ *Returns:* `*this`.
12372
+
12373
+ [*Note 3*: Iterators previously obtained from `other` are not
12374
+ invalidated; they become iterators into `*this`. — *end note*]
12375
+
12376
+ ``` cpp
12377
+ iterator begin();
12378
+ ```
12379
+
12380
+ *Preconditions:* *coroutine\_* refers to a coroutine suspended at its
12381
+ initial suspend point [[dcl.fct.def.coroutine]].
12382
+
12383
+ *Effects:* Pushes *coroutine\_* into `*`*`active_`*, then evaluates
12384
+ *`coroutine_`*`.resume()`.
12385
+
12386
+ *Returns:* An *iterator* object whose member *coroutine\_* refers to the
12387
+ same coroutine as does *coroutine\_*.
12388
+
12389
+ [*Note 4*: A program that calls `begin` more than once on the same
12390
+ generator has undefined behavior. — *end note*]
12391
+
12392
+ ``` cpp
12393
+ default_sentinel_t end() const noexcept;
12394
+ ```
12395
+
12396
+ *Returns:* `default_sentinel`.
12397
+
12398
+ ### Class `generator::promise_type` <a id="coro.generator.promise">[[coro.generator.promise]]</a>
12399
+
12400
+ ``` cpp
12401
+ namespace std {
12402
+ template<class Ref, class V, class Allocator>
12403
+ class generator<Ref, V, Allocator>::promise_type {
12404
+ public:
12405
+ generator get_return_object() noexcept;
12406
+
12407
+ suspend_always initial_suspend() const noexcept { return {}; }
12408
+ auto final_suspend() noexcept;
12409
+
12410
+ suspend_always yield_value(yielded val) noexcept;
12411
+
12412
+ auto yield_value(const remove_reference_t<yielded>& lval)
12413
+ requires is_rvalue_reference_v<yielded> &&
12414
+ constructible_from<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>;
12415
+
12416
+ template<class R2, class V2, class Alloc2, class Unused>
12417
+ requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded>
12418
+ auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept;
12419
+
12420
+ template<ranges::input_range R, class Alloc>
12421
+ requires convertible_to<ranges::range_reference_t<R>, yielded>
12422
+ auto yield_value(ranges::elements_of<R, Alloc> r) noexcept;
12423
+
12424
+ void await_transform() = delete;
12425
+
12426
+ void return_void() const noexcept {}
12427
+ void unhandled_exception();
12428
+
12429
+ void* operator new(size_t size)
12430
+ requires same_as<Allocator, void> || default_initializable<Allocator>;
12431
+
12432
+ template<class Alloc, class... Args>
12433
+ requires same_as<Allocator, void> || convertible_to<const Alloc&, Allocator>
12434
+ void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...);
12435
+
12436
+ template<class This, class Alloc, class... Args>
12437
+ requires same_as<Allocator, void> || convertible_to<const Alloc&, Allocator>
12438
+ void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc,
12439
+ const Args&...);
12440
+
12441
+ void operator delete(void* pointer, size_t size) noexcept;
12442
+
12443
+ private:
12444
+ add_pointer_t<yielded> value_ = nullptr; // exposition only
12445
+ exception_ptr except_; // exposition only
12446
+ };
12447
+ }
12448
+ ```
12449
+
12450
+ ``` cpp
12451
+ generator get_return_object() noexcept;
12452
+ ```
12453
+
12454
+ *Returns:* A `generator` object whose member *coroutine\_* is
12455
+ `coroutine_handle<promise_type>::from_promise(*this)`, and whose member
12456
+ *active\_* points to an empty stack.
12457
+
12458
+ ``` cpp
12459
+ auto final_suspend() noexcept;
12460
+ ```
12461
+
12462
+ *Preconditions:* A handle referring to the coroutine whose promise
12463
+ object is `*this` is at the top of `*`*`active_`* of some `generator`
12464
+ object `x`. This function is called by that coroutine upon reaching its
12465
+ final suspend point [[dcl.fct.def.coroutine]].
12466
+
12467
+ *Returns:* An awaitable object of unspecified type [[expr.await]] whose
12468
+ member functions arrange for the calling coroutine to be suspended, pop
12469
+ the coroutine handle from the top of `*x.`*`active_`*, and resume
12470
+ execution of the coroutine referred to by `x.`*`active_`*`->top()` if
12471
+ `*x.`*`active_`* is not empty. If it is empty, control flow returns to
12472
+ the current coroutine caller or resumer [[dcl.fct.def.coroutine]].
12473
+
12474
+ ``` cpp
12475
+ suspend_always yield_value(yielded val) noexcept;
12476
+ ```
12477
+
12478
+ *Effects:* Equivalent to *`value_`*` = addressof(val)`.
12479
+
12480
+ *Returns:* `{}`.
12481
+
12482
+ ``` cpp
12483
+ auto yield_value(const remove_reference_t<yielded>& lval)
12484
+ requires is_rvalue_reference_v<yielded> &&
12485
+ constructible_from<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>;
12486
+ ```
12487
+
12488
+ *Preconditions:* A handle referring to the coroutine whose promise
12489
+ object is `*this` is at the top of `*`*`active_`* of some `generator`
12490
+ object.
12491
+
12492
+ *Returns:* An awaitable object of an unspecified type [[expr.await]]
12493
+ that stores an object of type `remove_cvref_t<yielded>`
12494
+ direct-non-list-initialized with `lval`, whose member functions arrange
12495
+ for *value\_* to point to that stored object and then suspend the
12496
+ coroutine.
12497
+
12498
+ *Throws:* Any exception thrown by the initialization of the stored
12499
+ object.
12500
+
12501
+ *Remarks:* A *yield-expression* that calls this function has type `void`
12502
+ [[expr.yield]].
12503
+
12504
+ ``` cpp
12505
+ template<class R2, class V2, class Alloc2, class Unused>
12506
+ requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded>
12507
+ auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept;
12508
+ ```
12509
+
12510
+ *Preconditions:* A handle referring to the coroutine whose promise
12511
+ object is `*this` is at the top of `*`*`active_`* of some `generator`
12512
+ object `x`. The coroutine referred to by `g.range.`*`coroutine_`* is
12513
+ suspended at its initial suspend point.
12514
+
12515
+ *Returns:* An awaitable object of an unspecified type [[expr.await]]
12516
+ into which `g.range` is moved, whose member `await_ready` returns
12517
+ `false`, whose member `await_suspend` pushes
12518
+ `g.range.`\textit{coroutine\_} into `*x.`*`active_`* and resumes
12519
+ execution of the coroutine referred to by `g.range.`*`coroutine_`*, and
12520
+ whose member `await_resume` evaluates `rethrow_exception(`*`except_`*`)`
12521
+ if `bool(`*`except_`*`)` is `true`. If `bool(`*`except_`*`)` is `false`,
12522
+ the `await_resume` member has no effects.
12523
+
12524
+ *Remarks:* A *yield-expression* that calls this function has type `void`
12525
+ [[expr.yield]].
12526
+
12527
+ ``` cpp
12528
+ template<ranges::input_range R, class Alloc>
12529
+ requires convertible_to<ranges::range_reference_t<R>, yielded>
12530
+ auto yield_value(ranges::elements_of<R, Alloc> r) noexcept;
12531
+ ```
12532
+
12533
+ *Effects:* Equivalent to:
12534
+
12535
+ ``` cpp
12536
+ auto nested = [](allocator_arg_t, Alloc, ranges::iterator_t<R> i, ranges::sentinel_t<R> s)
12537
+ -> generator<yielded, ranges::range_value_t<R>, Alloc> {
12538
+ for (; i != s; ++i) {
12539
+ co_yield static_cast<yielded>(*i);
12540
+ }
12541
+ };
12542
+ return yield_value(ranges::elements_of(nested(
12543
+ allocator_arg, r.allocator, ranges::begin(r.range), ranges::end(r.range))));
12544
+ ```
12545
+
12546
+ [*Note 1*: A *yield-expression* that calls this function has type
12547
+ `void` [[expr.yield]]. — *end note*]
12548
+
12549
+ ``` cpp
12550
+ void unhandled_exception();
12551
+ ```
12552
+
12553
+ *Preconditions:* A handle referring to the coroutine whose promise
12554
+ object is `*this` is at the top of `*`*`active_`* of some `generator`
12555
+ object `x`.
12556
+
12557
+ *Effects:* If the handle referring to the coroutine whose promise object
12558
+ is `*this` is the sole element of `*x.`*`active_`*, equivalent to
12559
+ `throw`, otherwise, assigns `current_exception()` to *except\_*.
12560
+
12561
+ ``` cpp
12562
+ void* operator new(size_t size)
12563
+ requires same_as<Allocator, void> || default_initializable<Allocator>;
12564
+
12565
+ template<class Alloc, class... Args>
12566
+ requires same_as<Allocator, void> || convertible_to<const Alloc&, Allocator>
12567
+ void* operator new(size_t size, allocator_arg_t, const Alloc& alloc, const Args&...);
12568
+
12569
+ template<class This, class Alloc, class... Args>
12570
+ requires same_as<Allocator, void> || convertible_to<const Alloc&, Allocator>
12571
+ void* operator new(size_t size, const This&, allocator_arg_t, const Alloc& alloc,
12572
+ const Args&...);
12573
+ ```
12574
+
12575
+ Let `A` be
12576
+
12577
+ - `Allocator`, if it is not `void`,
12578
+ - `Alloc` for the overloads with a template parameter `Alloc`, or
12579
+ - `allocator<void>` otherwise.
12580
+
12581
+ Let `B` be `allocator_traits<A>::template rebind_alloc<U>` where `U` is
12582
+ an unspecified type whose size and alignment are both
12583
+ \_\_STDCPP_DEFAULT_NEW_ALIGNMENT\_\_.
12584
+
12585
+ *Mandates:* `allocator_traits<B>::pointer` is a pointer type.
12586
+
12587
+ *Effects:* Initializes an allocator `b` of type `B` with `A(alloc)`, for
12588
+ the overloads with a function parameter `alloc`, and with `A()`
12589
+ otherwise. Uses `b` to allocate storage for the smallest array of `U`
12590
+ sufficient to provide storage for a coroutine state of size `size`, and
12591
+ unspecified additional state necessary to ensure that `operator delete`
12592
+ can later deallocate this memory block with an allocator equal to `b`.
12593
+
12594
+ *Returns:* A pointer to the allocated storage.
12595
+
12596
+ ``` cpp
12597
+ void operator delete(void* pointer, size_t size) noexcept;
12598
+ ```
12599
+
12600
+ *Preconditions:* `pointer` was returned from an invocation of one of the
12601
+ above overloads of `operator new` with a `size` argument equal to
12602
+ `size`.
12603
+
12604
+ *Effects:* Deallocates the storage pointed to by `pointer` using an
12605
+ allocator equivalent to that used to allocate it.
12606
+
12607
+ ### Class `generator::iterator` <a id="coro.generator.iterator">[[coro.generator.iterator]]</a>
12608
+
12609
+ ``` cpp
12610
+ namespace std {
12611
+ template<class Ref, class V, class Allocator>
12612
+ class generator<Ref, V, Allocator>::iterator {
12613
+ public:
12614
+ using value_type = value;
12615
+ using difference_type = ptrdiff_t;
12616
+
12617
+ iterator(iterator&& other) noexcept;
12618
+ iterator& operator=(iterator&& other) noexcept;
12619
+
12620
+ reference operator*() const noexcept(is_nothrow_copy_constructible_v<reference>);
12621
+ iterator& operator++();
12622
+ void operator++(int);
12623
+
12624
+ friend bool operator==(const iterator& i, default_sentinel_t);
12625
+
12626
+ private:
12627
+ coroutine_handle<promise_type> coroutine_; // exposition only
12628
+ };
12629
+ }
12630
+ ```
12631
+
12632
+ ``` cpp
12633
+ iterator(iterator&& other) noexcept;
12634
+ ```
12635
+
12636
+ *Effects:* Initializes *coroutine\_* with
12637
+ `exchange(other.`*`coroutine_`*`, {})`.
12638
+
12639
+ ``` cpp
12640
+ iterator& operator=(iterator&& other) noexcept;
12641
+ ```
12642
+
12643
+ *Effects:* Equivalent to
12644
+ *`coroutine_`*` = exchange(other.`*`coroutine_`*`, {})`.
12645
+
12646
+ *Returns:* `*this`.
12647
+
12648
+ ``` cpp
12649
+ reference operator*() const noexcept(is_nothrow_copy_constructible_v<reference>);
12650
+ ```
12651
+
12652
+ *Preconditions:* For some `generator` object `x`, *coroutine\_* is in
12653
+ `*x.`*`active_`* and `x.`*`active_`*`->top()` refers to a suspended
12654
+ coroutine with promise object `p`.
12655
+
12656
+ *Effects:* Equivalent to:
12657
+ `return static_cast<`*`reference`*`>(*p.`*`value_`*`);`
12658
+
12659
+ ``` cpp
12660
+ iterator& operator++();
12661
+ ```
12662
+
12663
+ *Preconditions:* For some `generator` object `x`, *coroutine\_* is in
12664
+ `*x.`*`active_`*.
12665
+
12666
+ *Effects:* Equivalent to `x.`*`active_`*`->top().resume()`.
12667
+
12668
+ *Returns:* `*this`.
12669
+
12670
+ ``` cpp
12671
+ void operator++(int);
12672
+ ```
12673
+
12674
+ *Effects:* Equivalent to `++*this`.
12675
+
12676
+ ``` cpp
12677
+ friend bool operator==(const iterator& i, default_sentinel_t);
12678
+ ```
12679
+
12680
+ *Effects:* Equivalent to: `return i.`*`coroutine_`*`.done();`
12681
+
12682
  <!-- Link reference definitions -->
12683
+ [basic.lookup.argdep]: basic.md#basic.lookup.argdep
12684
  [concepts.equality]: concepts.md#concepts.equality
12685
  [containers]: containers.md#containers
12686
  [conv.rval]: expr.md#conv.rval
12687
+ [coro.generator]: #coro.generator
12688
+ [coro.generator.class]: #coro.generator.class
12689
+ [coro.generator.iterator]: #coro.generator.iterator
12690
+ [coro.generator.members]: #coro.generator.members
12691
+ [coro.generator.promise]: #coro.generator.promise
12692
+ [coroutine.generator.overview]: #coroutine.generator.overview
12693
  [customization.point.object]: library.md#customization.point.object
12694
+ [dcl.fct.def.coroutine]: dcl.md#dcl.fct.def.coroutine
12695
+ [dcl.init.general]: dcl.md#dcl.init.general
12696
+ [expr.await]: expr.md#expr.await
12697
  [expr.const]: expr.md#expr.const
12698
+ [expr.yield]: expr.md#expr.yield
12699
+ [generator.syn]: #generator.syn
12700
  [iterator.concept.bidir]: iterators.md#iterator.concept.bidir
12701
+ [iterator.concept.forward]: iterators.md#iterator.concept.forward
12702
  [iterator.concept.iterator]: iterators.md#iterator.concept.iterator
12703
  [iterator.concept.output]: iterators.md#iterator.concept.output
12704
  [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
12705
  [iterator.concept.sizedsentinel]: iterators.md#iterator.concept.sizedsentinel
12706
  [iterator.concept.winc]: iterators.md#iterator.concept.winc
 
12711
  [range.access.cbegin]: #range.access.cbegin
12712
  [range.access.cend]: #range.access.cend
12713
  [range.access.crbegin]: #range.access.crbegin
12714
  [range.access.crend]: #range.access.crend
12715
  [range.access.end]: #range.access.end
12716
+ [range.access.general]: #range.access.general
12717
  [range.access.rbegin]: #range.access.rbegin
12718
  [range.access.rend]: #range.access.rend
12719
+ [range.adaptor.helpers]: #range.adaptor.helpers
12720
  [range.adaptor.object]: #range.adaptor.object
12721
  [range.adaptors]: #range.adaptors
12722
+ [range.adaptors.general]: #range.adaptors.general
12723
+ [range.adjacent]: #range.adjacent
12724
+ [range.adjacent.iterator]: #range.adjacent.iterator
12725
+ [range.adjacent.overview]: #range.adjacent.overview
12726
+ [range.adjacent.sentinel]: #range.adjacent.sentinel
12727
+ [range.adjacent.transform]: #range.adjacent.transform
12728
+ [range.adjacent.transform.iterator]: #range.adjacent.transform.iterator
12729
+ [range.adjacent.transform.overview]: #range.adjacent.transform.overview
12730
+ [range.adjacent.transform.sentinel]: #range.adjacent.transform.sentinel
12731
+ [range.adjacent.transform.view]: #range.adjacent.transform.view
12732
+ [range.adjacent.view]: #range.adjacent.view
12733
  [range.all]: #range.all
12734
+ [range.all.general]: #range.all.general
12735
+ [range.as.const]: #range.as.const
12736
+ [range.as.const.overview]: #range.as.const.overview
12737
+ [range.as.const.view]: #range.as.const.view
12738
+ [range.as.rvalue]: #range.as.rvalue
12739
+ [range.as.rvalue.overview]: #range.as.rvalue.overview
12740
+ [range.as.rvalue.view]: #range.as.rvalue.view
12741
+ [range.cartesian]: #range.cartesian
12742
+ [range.cartesian.iterator]: #range.cartesian.iterator
12743
+ [range.cartesian.overview]: #range.cartesian.overview
12744
+ [range.cartesian.view]: #range.cartesian.view
12745
+ [range.chunk]: #range.chunk
12746
+ [range.chunk.by]: #range.chunk.by
12747
+ [range.chunk.by.iter]: #range.chunk.by.iter
12748
+ [range.chunk.by.overview]: #range.chunk.by.overview
12749
+ [range.chunk.by.view]: #range.chunk.by.view
12750
+ [range.chunk.fwd.iter]: #range.chunk.fwd.iter
12751
+ [range.chunk.inner.iter]: #range.chunk.inner.iter
12752
+ [range.chunk.outer.iter]: #range.chunk.outer.iter
12753
+ [range.chunk.outer.value]: #range.chunk.outer.value
12754
+ [range.chunk.overview]: #range.chunk.overview
12755
+ [range.chunk.view.fwd]: #range.chunk.view.fwd
12756
+ [range.chunk.view.input]: #range.chunk.view.input
12757
  [range.common]: #range.common
12758
  [range.common.overview]: #range.common.overview
12759
  [range.common.view]: #range.common.view
12760
  [range.counted]: #range.counted
12761
  [range.dangling]: #range.dangling
 
12768
  [range.elements]: #range.elements
12769
  [range.elements.iterator]: #range.elements.iterator
12770
  [range.elements.overview]: #range.elements.overview
12771
  [range.elements.sentinel]: #range.elements.sentinel
12772
  [range.elements.view]: #range.elements.view
12773
+ [range.elementsof]: #range.elementsof
12774
  [range.empty]: #range.empty
12775
  [range.empty.overview]: #range.empty.overview
12776
  [range.empty.view]: #range.empty.view
12777
+ [range.enumerate]: #range.enumerate
12778
+ [range.enumerate.iterator]: #range.enumerate.iterator
12779
+ [range.enumerate.overview]: #range.enumerate.overview
12780
+ [range.enumerate.sentinel]: #range.enumerate.sentinel
12781
+ [range.enumerate.view]: #range.enumerate.view
12782
  [range.factories]: #range.factories
12783
+ [range.factories.general]: #range.factories.general
12784
  [range.filter]: #range.filter
12785
  [range.filter.iterator]: #range.filter.iterator
12786
  [range.filter.overview]: #range.filter.overview
12787
  [range.filter.sentinel]: #range.filter.sentinel
12788
  [range.filter.view]: #range.filter.view
 
12798
  [range.join]: #range.join
12799
  [range.join.iterator]: #range.join.iterator
12800
  [range.join.overview]: #range.join.overview
12801
  [range.join.sentinel]: #range.join.sentinel
12802
  [range.join.view]: #range.join.view
12803
+ [range.join.with]: #range.join.with
12804
+ [range.join.with.iterator]: #range.join.with.iterator
12805
+ [range.join.with.overview]: #range.join.with.overview
12806
+ [range.join.with.sentinel]: #range.join.with.sentinel
12807
+ [range.join.with.view]: #range.join.with.view
12808
+ [range.lazy.split]: #range.lazy.split
12809
+ [range.lazy.split.inner]: #range.lazy.split.inner
12810
+ [range.lazy.split.outer]: #range.lazy.split.outer
12811
+ [range.lazy.split.outer.value]: #range.lazy.split.outer.value
12812
+ [range.lazy.split.overview]: #range.lazy.split.overview
12813
+ [range.lazy.split.view]: #range.lazy.split.view
12814
+ [range.move.wrap]: #range.move.wrap
12815
+ [range.nonprop.cache]: #range.nonprop.cache
12816
+ [range.owning.view]: #range.owning.view
12817
  [range.prim.cdata]: #range.prim.cdata
12818
  [range.prim.data]: #range.prim.data
12819
  [range.prim.empty]: #range.prim.empty
12820
  [range.prim.size]: #range.prim.size
12821
  [range.prim.ssize]: #range.prim.ssize
12822
  [range.range]: #range.range
12823
  [range.ref.view]: #range.ref.view
12824
  [range.refinements]: #range.refinements
12825
+ [range.repeat]: #range.repeat
12826
+ [range.repeat.iterator]: #range.repeat.iterator
12827
+ [range.repeat.overview]: #range.repeat.overview
12828
+ [range.repeat.view]: #range.repeat.view
12829
  [range.req]: #range.req
12830
  [range.req.general]: #range.req.general
12831
  [range.reverse]: #range.reverse
12832
  [range.reverse.overview]: #range.reverse.overview
12833
  [range.reverse.view]: #range.reverse.view
 
12834
  [range.single]: #range.single
12835
  [range.single.overview]: #range.single.overview
12836
  [range.single.view]: #range.single.view
12837
  [range.sized]: #range.sized
12838
+ [range.slide]: #range.slide
12839
+ [range.slide.iterator]: #range.slide.iterator
12840
+ [range.slide.overview]: #range.slide.overview
12841
+ [range.slide.sentinel]: #range.slide.sentinel
12842
+ [range.slide.view]: #range.slide.view
12843
  [range.split]: #range.split
12844
+ [range.split.iterator]: #range.split.iterator
 
 
12845
  [range.split.overview]: #range.split.overview
12846
+ [range.split.sentinel]: #range.split.sentinel
12847
  [range.split.view]: #range.split.view
12848
+ [range.stride]: #range.stride
12849
+ [range.stride.iterator]: #range.stride.iterator
12850
+ [range.stride.overview]: #range.stride.overview
12851
+ [range.stride.view]: #range.stride.view
12852
  [range.subrange]: #range.subrange
12853
  [range.subrange.access]: #range.subrange.access
12854
  [range.subrange.ctor]: #range.subrange.ctor
12855
+ [range.subrange.general]: #range.subrange.general
12856
  [range.summary]: #range.summary
12857
  [range.take]: #range.take
12858
  [range.take.overview]: #range.take.overview
12859
  [range.take.sentinel]: #range.take.sentinel
12860
  [range.take.view]: #range.take.view
 
12866
  [range.transform.iterator]: #range.transform.iterator
12867
  [range.transform.overview]: #range.transform.overview
12868
  [range.transform.sentinel]: #range.transform.sentinel
12869
  [range.transform.view]: #range.transform.view
12870
  [range.utility]: #range.utility
12871
+ [range.utility.conv]: #range.utility.conv
12872
+ [range.utility.conv.adaptors]: #range.utility.conv.adaptors
12873
+ [range.utility.conv.general]: #range.utility.conv.general
12874
+ [range.utility.conv.to]: #range.utility.conv.to
12875
+ [range.utility.general]: #range.utility.general
12876
  [range.utility.helpers]: #range.utility.helpers
12877
  [range.view]: #range.view
12878
+ [range.zip]: #range.zip
12879
+ [range.zip.iterator]: #range.zip.iterator
12880
+ [range.zip.overview]: #range.zip.overview
12881
+ [range.zip.sentinel]: #range.zip.sentinel
12882
+ [range.zip.transform]: #range.zip.transform
12883
+ [range.zip.transform.iterator]: #range.zip.transform.iterator
12884
+ [range.zip.transform.overview]: #range.zip.transform.overview
12885
+ [range.zip.transform.sentinel]: #range.zip.transform.sentinel
12886
+ [range.zip.transform.view]: #range.zip.transform.view
12887
+ [range.zip.view]: #range.zip.view
12888
  [ranges]: #ranges
12889
  [ranges.general]: #ranges.general
12890
  [ranges.syn]: #ranges.syn
12891
  [string.view]: strings.md#string.view
12892
+ [term.array.type]: dcl.md#term.array.type
12893
+ [term.perfect.forwarding.call.wrapper]: utilities.md#term.perfect.forwarding.call.wrapper
12894
  [view.interface]: #view.interface
12895
+ [view.interface.general]: #view.interface.general
12896
  [view.interface.members]: #view.interface.members
12897
  [views.span]: containers.md#views.span