From Jason Turner

[range.utility]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpsgk6o4n8/{from.md → to.md} +459 -0
tmp/tmpsgk6o4n8/{from.md → to.md} RENAMED
@@ -0,0 +1,459 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Range utilities <a id="range.utility">[[range.utility]]</a>
2
+
3
+ The components in this subclause are general utilities for representing
4
+ and manipulating ranges.
5
+
6
+ ### Helper concepts <a id="range.utility.helpers">[[range.utility.helpers]]</a>
7
+
8
+ Many of the types in subclause  [[range.utility]] are specified in terms
9
+ of the following exposition-only concepts:
10
+
11
+ ``` cpp
12
+ template<class R>
13
+ concept simple-view = // exposition only
14
+ view<R> && range<const R> &&
15
+ same_as<iterator_t<R>, iterator_t<const R>> &&
16
+ same_as<sentinel_t<R>, sentinel_t<const R>>;
17
+
18
+ template<class I>
19
+ concept has-arrow = // exposition only
20
+ input_iterator<I> && (is_pointer_v<I> || requires(I i) { i.operator->(); });
21
+
22
+ template<class T, class U>
23
+ concept not-same-as = // exposition only
24
+ !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
25
+ ```
26
+
27
+ ### View interface <a id="view.interface">[[view.interface]]</a>
28
+
29
+ The class template `view_interface` is a helper for defining `view`-like
30
+ types that offer a container-like interface. It is parameterized with
31
+ the type that is derived from it.
32
+
33
+ ``` cpp
34
+ namespace std::ranges {
35
+ template<class D>
36
+ requires is_class_v<D> && same_as<D, remove_cv_t<D>>
37
+ class view_interface : public view_base {
38
+ private:
39
+ constexpr D& derived() noexcept { // exposition only
40
+ return static_cast<D&>(*this);
41
+ }
42
+ constexpr const D& derived() const noexcept { // exposition only
43
+ return static_cast<const D&>(*this);
44
+ }
45
+ public:
46
+ constexpr bool empty() requires forward_range<D> {
47
+ return ranges::begin(derived()) == ranges::end(derived());
48
+ }
49
+ constexpr bool empty() const requires forward_range<const D> {
50
+ return ranges::begin(derived()) == ranges::end(derived());
51
+ }
52
+
53
+ constexpr explicit operator bool()
54
+ requires requires { ranges::empty(derived()); } {
55
+ return !ranges::empty(derived());
56
+ }
57
+ constexpr explicit operator bool() const
58
+ requires requires { ranges::empty(derived()); } {
59
+ return !ranges::empty(derived());
60
+ }
61
+
62
+ constexpr auto data() requires contiguous_iterator<iterator_t<D>> {
63
+ return to_address(ranges::begin(derived()));
64
+ }
65
+ constexpr auto data() const
66
+ requires range<const D> && contiguous_iterator<iterator_t<const D>> {
67
+ return to_address(ranges::begin(derived()));
68
+ }
69
+
70
+ constexpr auto size() requires forward_range<D> &&
71
+ sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
72
+ return ranges::end(derived()) - ranges::begin(derived());
73
+ }
74
+ constexpr auto size() const requires forward_range<const D> &&
75
+ sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
76
+ return ranges::end(derived()) - ranges::begin(derived());
77
+ }
78
+
79
+ constexpr decltype(auto) front() requires forward_range<D>;
80
+ constexpr decltype(auto) front() const requires forward_range<const D>;
81
+
82
+ constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
83
+ constexpr decltype(auto) back() const
84
+ requires bidirectional_range<const D> && common_range<const D>;
85
+
86
+ template<random_access_range R = D>
87
+ constexpr decltype(auto) operator[](range_difference_t<R> n) {
88
+ return ranges::begin(derived())[n];
89
+ }
90
+ template<random_access_range R = const D>
91
+ constexpr decltype(auto) operator[](range_difference_t<R> n) const {
92
+ return ranges::begin(derived())[n];
93
+ }
94
+ };
95
+ }
96
+ ```
97
+
98
+ The template parameter `D` for `view_interface` may be an incomplete
99
+ type. Before any member of the resulting specialization of
100
+ `view_interface` other than special member functions is referenced, `D`
101
+ shall be complete, and model both `derived_from<view_interface<D>>` and
102
+ `view`.
103
+
104
+ #### Members <a id="view.interface.members">[[view.interface.members]]</a>
105
+
106
+ ``` cpp
107
+ constexpr decltype(auto) front() requires forward_range<D>;
108
+ constexpr decltype(auto) front() const requires forward_range<const D>;
109
+ ```
110
+
111
+ *Preconditions:* `!empty()`.
112
+
113
+ *Effects:* Equivalent to: `return *ranges::begin(`*`derived`*`());`
114
+
115
+ ``` cpp
116
+ constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
117
+ constexpr decltype(auto) back() const
118
+ requires bidirectional_range<const D> && common_range<const D>;
119
+ ```
120
+
121
+ *Preconditions:* `!empty()`.
122
+
123
+ *Effects:* Equivalent to:
124
+ `return *ranges::prev(ranges::end(`*`derived`*`()));`
125
+
126
+ ### Sub-ranges <a id="range.subrange">[[range.subrange]]</a>
127
+
128
+ The `subrange` class template combines together an iterator and a
129
+ sentinel into a single object that models the `view` concept.
130
+ Additionally, it models the `sized_range` concept when the final
131
+ template parameter is `subrange_kind::sized`.
132
+
133
+ ``` cpp
134
+ namespace std::ranges {
135
+ template<class From, class To>
136
+ concept convertible-to-non-slicing = // exposition only
137
+ convertible_to<From, To> &&
138
+ !(is_pointer_v<decay_t<From>> &&
139
+ is_pointer_v<decay_t<To>> &&
140
+ not-same-as<remove_pointer_t<decay_t<From>>, remove_pointer_t<decay_t<To>>>);
141
+
142
+ template<class T>
143
+ concept pair-like = // exposition only
144
+ !is_reference_v<T> && requires(T t) {
145
+ typename tuple_size<T>::type; // ensures tuple_size<T> is complete
146
+ requires derived_from<tuple_size<T>, integral_constant<size_t, 2>>;
147
+ typename tuple_element_t<0, remove_const_t<T>>;
148
+ typename tuple_element_t<1, remove_const_t<T>>;
149
+ { get<0>(t) } -> convertible_to<const tuple_element_t<0, T>&>;
150
+ { get<1>(t) } -> convertible_to<const tuple_element_t<1, T>&>;
151
+ };
152
+
153
+ template<class T, class U, class V>
154
+ concept pair-like-convertible-from = // exposition only
155
+ !range<T> && pair-like<T> &&
156
+ constructible_from<T, U, V> &&
157
+ convertible-to-non-slicing<U, tuple_element_t<0, T>> &&
158
+ convertible_to<V, tuple_element_t<1, T>>;
159
+
160
+ template<class T>
161
+ concept iterator-sentinel-pair = // exposition only
162
+ !range<T> && pair-like<T> &&
163
+ sentinel_for<tuple_element_t<1, T>, tuple_element_t<0, T>>;
164
+
165
+ template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
166
+ sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
167
+ requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
168
+ class subrange : public view_interface<subrange<I, S, K>> {
169
+ private:
170
+ static constexpr bool StoreSize = // exposition only
171
+ K == subrange_kind::sized && !sized_sentinel_for<S, I>;
172
+ I begin_ = I(); // exposition only
173
+ S end_ = S(); // exposition only
174
+ make-unsigned-like-t<iter_difference_t<I>> size_ = 0; // exposition only; present only
175
+ // when StoreSize is true
176
+ public:
177
+ subrange() = default;
178
+
179
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
180
+
181
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
182
+ make-unsigned-like-t<iter_difference_t<I>> n)
183
+ requires (K == subrange_kind::sized);
184
+
185
+ template<not-same-as<subrange> R>
186
+ requires borrowed_range<R> &&
187
+ convertible-to-non-slicing<iterator_t<R>, I> &&
188
+ convertible_to<sentinel_t<R>, S>
189
+ constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
190
+
191
+ template<borrowed_range R>
192
+ requires convertible-to-non-slicing<iterator_t<R>, I> &&
193
+ convertible_to<sentinel_t<R>, S>
194
+ constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
195
+ requires (K == subrange_kind::sized)
196
+ : subrange{ranges::begin(r), ranges::end(r), n}
197
+ {}
198
+
199
+ template<not-same-as<subrange> PairLike>
200
+ requires pair-like-convertible-from<PairLike, const I&, const S&>
201
+ constexpr operator PairLike() const;
202
+
203
+ constexpr I begin() const requires copyable<I>;
204
+ [[nodiscard]] constexpr I begin() requires (!copyable<I>);
205
+ constexpr S end() const;
206
+
207
+ constexpr bool empty() const;
208
+ constexpr make-unsigned-like-t<iter_difference_t<I>> size() const
209
+ requires (K == subrange_kind::sized);
210
+
211
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const &
212
+ requires forward_iterator<I>;
213
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;
214
+ [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
215
+ requires bidirectional_iterator<I>;
216
+ constexpr subrange& advance(iter_difference_t<I> n);
217
+ };
218
+
219
+ template<input_or_output_iterator I, sentinel_for<I> S>
220
+ subrange(I, S) -> subrange<I, S>;
221
+
222
+ template<input_or_output_iterator I, sentinel_for<I> S>
223
+ subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) ->
224
+ subrange<I, S, subrange_kind::sized>;
225
+
226
+ template<iterator-sentinel-pair P>
227
+ subrange(P) -> subrange<tuple_element_t<0, P>, tuple_element_t<1, P>>;
228
+
229
+ template<iterator-sentinel-pair P>
230
+ subrange(P, make-unsigned-like-t<iter_difference_t<tuple_element_t<0, P>>>) ->
231
+ subrange<tuple_element_t<0, P>, tuple_element_t<1, P>, subrange_kind::sized>;
232
+
233
+ template<borrowed_range R>
234
+ subrange(R&&) ->
235
+ subrange<iterator_t<R>, sentinel_t<R>,
236
+ (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
237
+ ? subrange_kind::sized : subrange_kind::unsized>;
238
+
239
+ template<borrowed_range R>
240
+ subrange(R&&, make-unsigned-like-t<range_difference_t<R>>) ->
241
+ subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
242
+
243
+ template<size_t N, class I, class S, subrange_kind K>
244
+ requires (N < 2)
245
+ constexpr auto get(const subrange<I, S, K>& r);
246
+
247
+ template<size_t N, class I, class S, subrange_kind K>
248
+ requires (N < 2)
249
+ constexpr auto get(subrange<I, S, K>&& r);
250
+ }
251
+
252
+ namespace std {
253
+ using ranges::get;
254
+ }
255
+ ```
256
+
257
+ #### Constructors and conversions <a id="range.subrange.ctor">[[range.subrange.ctor]]</a>
258
+
259
+ ``` cpp
260
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
261
+ ```
262
+
263
+ *Preconditions:* \[`i`, `s`) is a valid range.
264
+
265
+ *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
266
+ `s`.
267
+
268
+ ``` cpp
269
+ constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
270
+ make-unsigned-like-t<iter_difference_t<I>> n)
271
+ requires (K == subrange_kind::sized);
272
+ ```
273
+
274
+ *Preconditions:* \[`i`, `s`) is a valid range, and
275
+ `n == `*`to-unsigned-like`*`(ranges::distance(i, s))`.
276
+
277
+ *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
278
+ `s`. If *StoreSize* is `true`, initializes *size\_* with `n`.
279
+
280
+ [*Note 1*: Accepting the length of the range and storing it to later
281
+ return from `size()` enables `subrange` to model `sized_range` even when
282
+ it stores an iterator and sentinel that do not model
283
+ `sized_sentinel_for`. — *end note*]
284
+
285
+ ``` cpp
286
+ template<not-same-as<subrange> R>
287
+ requires borrowed_range<R> &&
288
+ convertible-to-non-slicing<iterator_t<R>, I> &&
289
+ convertible_to<sentinel_t<R>, S>
290
+ constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
291
+ ```
292
+
293
+ *Effects:* Equivalent to:
294
+
295
+ - If *StoreSize* is `true`, `subrange{r, ranges::size(r)}`.
296
+ - Otherwise, `subrange{ranges::begin(r), ranges::end(r)}`.
297
+
298
+ ``` cpp
299
+ template<not-same-as<subrange> PairLike>
300
+ requires pair-like-convertible-from<PairLike, const I&, const S&>
301
+ constexpr operator PairLike() const;
302
+ ```
303
+
304
+ *Effects:* Equivalent to: `return PairLike(`*`begin_`*`, `*`end_`*`);`
305
+
306
+ #### Accessors <a id="range.subrange.access">[[range.subrange.access]]</a>
307
+
308
+ ``` cpp
309
+ constexpr I begin() const requires copyable<I>;
310
+ ```
311
+
312
+ *Effects:* Equivalent to: `return `*`begin_`*`;`
313
+
314
+ ``` cpp
315
+ [[nodiscard]] constexpr I begin() requires (!copyable<I>);
316
+ ```
317
+
318
+ *Effects:* Equivalent to: `return std::move(`*`begin_`*`);`
319
+
320
+ ``` cpp
321
+ constexpr S end() const;
322
+ ```
323
+
324
+ *Effects:* Equivalent to: `return `*`end_`*`;`
325
+
326
+ ``` cpp
327
+ constexpr bool empty() const;
328
+ ```
329
+
330
+ *Effects:* Equivalent to: `return `*`begin_`*` == `*`end_`*`;`
331
+
332
+ ``` cpp
333
+ constexpr make-unsigned-like-t<iter_difference_t<I>> size() const
334
+ requires (K == subrange_kind::sized);
335
+ ```
336
+
337
+ *Effects:*
338
+
339
+ - If *StoreSize* is `true`, equivalent to: `return `*`size_`*`;`
340
+ - Otherwise, equivalent to:
341
+ `return `*`to-unsigned-like`*`(`*`end_`*` - `*`begin_`*`);`
342
+
343
+ ``` cpp
344
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) const &
345
+ requires forward_iterator<I>;
346
+ ```
347
+
348
+ *Effects:* Equivalent to:
349
+
350
+ ``` cpp
351
+ auto tmp = *this;
352
+ tmp.advance(n);
353
+ return tmp;
354
+ ```
355
+
356
+ ``` cpp
357
+ [[nodiscard]] constexpr subrange next(iter_difference_t<I> n = 1) &&;
358
+ ```
359
+
360
+ *Effects:* Equivalent to:
361
+
362
+ ``` cpp
363
+ advance(n);
364
+ return std::move(*this);
365
+ ```
366
+
367
+ ``` cpp
368
+ [[nodiscard]] constexpr subrange prev(iter_difference_t<I> n = 1) const
369
+ requires bidirectional_iterator<I>;
370
+ ```
371
+
372
+ *Effects:* Equivalent to:
373
+
374
+ ``` cpp
375
+ auto tmp = *this;
376
+ tmp.advance(-n);
377
+ return tmp;
378
+ ```
379
+
380
+ ``` cpp
381
+ constexpr subrange& advance(iter_difference_t<I> n);
382
+ ```
383
+
384
+ *Effects:* Equivalent to:
385
+
386
+ - If *StoreSize* is `true`,
387
+ ``` cpp
388
+ auto d = n - ranges::advance(begin_, n, end_);
389
+ if (d >= 0)
390
+ size_ -= to-unsigned-like(d);
391
+ else
392
+ size_ += to-unsigned-like(-d);
393
+ return *this;
394
+ ```
395
+ - Otherwise,
396
+ ``` cpp
397
+ ranges::advance(begin_, n, end_);
398
+ return *this;
399
+ ```
400
+
401
+ ``` cpp
402
+ template<size_t N, class I, class S, subrange_kind K>
403
+ requires (N < 2)
404
+ constexpr auto get(const subrange<I, S, K>& r);
405
+ template<size_t N, class I, class S, subrange_kind K>
406
+ requires (N < 2)
407
+ constexpr auto get(subrange<I, S, K>&& r);
408
+ ```
409
+
410
+ *Effects:* Equivalent to:
411
+
412
+ ``` cpp
413
+ if constexpr (N == 0)
414
+ return r.begin();
415
+ else
416
+ return r.end();
417
+ ```
418
+
419
+ ### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
420
+
421
+ The tag type `dangling` is used together with the template aliases
422
+ `borrowed_iterator_t` and `borrowed_subrange_t` to indicate that an
423
+ algorithm that typically returns an iterator into or subrange of a
424
+ `range` argument does not return an iterator or subrange which could
425
+ potentially reference a range whose lifetime has ended for a particular
426
+ rvalue `range` argument which does not model `borrowed_range`
427
+ [[range.range]].
428
+
429
+ ``` cpp
430
+ namespace std::ranges {
431
+ struct dangling {
432
+ constexpr dangling() noexcept = default;
433
+ template<class... Args>
434
+ constexpr dangling(Args&&...) noexcept { }
435
+ };
436
+ }
437
+ ```
438
+
439
+ [*Example 1*:
440
+
441
+ ``` cpp
442
+ vector<int> f();
443
+ auto result1 = ranges::find(f(), 42); // #1
444
+ static_assert(same_as<decltype(result1), ranges::dangling>);
445
+ auto vec = f();
446
+ auto result2 = ranges::find(vec, 42); // #2
447
+ static_assert(same_as<decltype(result2), vector<int>::iterator>);
448
+ auto result3 = ranges::find(subrange{vec}, 42); // #3
449
+ static_assert(same_as<decltype(result3), vector<int>::iterator>);
450
+ ```
451
+
452
+ The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
453
+ is an rvalue `vector`; the `vector` could potentially be destroyed
454
+ before a returned iterator is dereferenced. However, the calls at \#2
455
+ and \#3 both return iterators since the lvalue `vec` and specializations
456
+ of `subrange` model `borrowed_range`.
457
+
458
+ — *end example*]
459
+