From Jason Turner

[range.utility]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpq1l01rne/{from.md → to.md} +296 -82
tmp/tmpq1l01rne/{from.md → to.md} RENAMED
@@ -1,9 +1,11 @@
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:
@@ -18,40 +20,67 @@ template<class R>
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
@@ -67,15 +96,15 @@ namespace std::ranges {
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
 
@@ -106,99 +135,87 @@ shall be complete, and model both `derived_from<view_interface<D>>` and
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>);
@@ -221,38 +238,19 @@ namespace std::ranges {
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
 
@@ -270,35 +268,36 @@ 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_`*`);`
@@ -381,28 +380,29 @@ return tmp;
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
  ```
@@ -416,24 +416,23 @@ 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*:
@@ -443,17 +442,232 @@ 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ## Range utilities <a id="range.utility">[[range.utility]]</a>
2
 
3
+ ### General <a id="range.utility.general">[[range.utility.general]]</a>
4
+
5
+ The components in [[range.utility]] are general utilities for
6
+ representing and manipulating ranges.
7
 
8
  ### Helper concepts <a id="range.utility.helpers">[[range.utility.helpers]]</a>
9
 
10
  Many of the types in subclause  [[range.utility]] are specified in terms
11
  of the following exposition-only concepts:
 
20
  template<class I>
21
  concept has-arrow = // exposition only
22
  input_iterator<I> && (is_pointer_v<I> || requires(I i) { i.operator->(); });
23
 
24
  template<class T, class U>
25
+ concept different-from = // exposition only
26
  !same_as<remove_cvref_t<T>, remove_cvref_t<U>>;
27
+
28
+ template<class R>
29
+ concept range-with-movable-references = // exposition only
30
+ input_range<R> && move_constructible<range_reference_t<R>> &&
31
+ move_constructible<range_rvalue_reference_t<R>>;
32
  ```
33
 
34
  ### View interface <a id="view.interface">[[view.interface]]</a>
35
 
36
+ #### General <a id="view.interface.general">[[view.interface.general]]</a>
37
+
38
+ The class template `view_interface` is a helper for defining view-like
39
  types that offer a container-like interface. It is parameterized with
40
  the type that is derived from it.
41
 
42
  ``` cpp
43
  namespace std::ranges {
44
  template<class D>
45
  requires is_class_v<D> && same_as<D, remove_cv_t<D>>
46
+ class view_interface {
47
  private:
48
  constexpr D& derived() noexcept { // exposition only
49
  return static_cast<D&>(*this);
50
  }
51
  constexpr const D& derived() const noexcept { // exposition only
52
  return static_cast<const D&>(*this);
53
  }
54
+
55
  public:
56
+ constexpr bool empty() requires sized_range<D> || forward_range<D> {
57
+ if constexpr (sized_range<D>)
58
+ return ranges::size(derived()) == 0;
59
+ else
60
  return ranges::begin(derived()) == ranges::end(derived());
61
  }
62
+ constexpr bool empty() const requires sized_range<const D> || forward_range<const D> {
63
+ if constexpr (sized_range<const D>)
64
+ return ranges::size(derived()) == 0;
65
+ else
66
  return ranges::begin(derived()) == ranges::end(derived());
67
  }
68
 
69
+ constexpr auto cbegin() requires input_range<D> {
70
+ return ranges::cbegin(derived());
71
+ }
72
+ constexpr auto cbegin() const requires input_range<const D> {
73
+ return ranges::cbegin(derived());
74
+ }
75
+ constexpr auto cend() requires input_range<D> {
76
+ return ranges::cend(derived());
77
+ }
78
+ constexpr auto cend() const requires input_range<const D> {
79
+ return ranges::cend(derived());
80
+ }
81
+
82
  constexpr explicit operator bool()
83
  requires requires { ranges::empty(derived()); } {
84
  return !ranges::empty(derived());
85
  }
86
  constexpr explicit operator bool() const
 
96
  return to_address(ranges::begin(derived()));
97
  }
98
 
99
  constexpr auto size() requires forward_range<D> &&
100
  sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
101
+ return to-unsigned-like(ranges::end(derived()) - ranges::begin(derived()));
102
  }
103
  constexpr auto size() const requires forward_range<const D> &&
104
  sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
105
+ return to-unsigned-like(ranges::end(derived()) - ranges::begin(derived()));
106
  }
107
 
108
  constexpr decltype(auto) front() requires forward_range<D>;
109
  constexpr decltype(auto) front() const requires forward_range<const D>;
110
 
 
135
  ``` cpp
136
  constexpr decltype(auto) front() requires forward_range<D>;
137
  constexpr decltype(auto) front() const requires forward_range<const D>;
138
  ```
139
 
140
+ *Preconditions:* `!empty()` is `true`.
141
 
142
  *Effects:* Equivalent to: `return *ranges::begin(`*`derived`*`());`
143
 
144
  ``` cpp
145
  constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
146
  constexpr decltype(auto) back() const
147
  requires bidirectional_range<const D> && common_range<const D>;
148
  ```
149
 
150
+ *Preconditions:* `!empty()` is `true`.
151
 
152
  *Effects:* Equivalent to:
153
  `return *ranges::prev(ranges::end(`*`derived`*`()));`
154
 
155
  ### Sub-ranges <a id="range.subrange">[[range.subrange]]</a>
156
 
157
+ #### General <a id="range.subrange.general">[[range.subrange.general]]</a>
158
+
159
  The `subrange` class template combines together an iterator and a
160
  sentinel into a single object that models the `view` concept.
161
  Additionally, it models the `sized_range` concept when the final
162
  template parameter is `subrange_kind::sized`.
163
 
164
  ``` cpp
165
  namespace std::ranges {
166
+ template<class From, class To>
167
+ concept uses-nonqualification-pointer-conversion = // exposition only
168
+ is_pointer_v<From> && is_pointer_v<To> &&
169
+ !convertible_to<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>;
170
+
171
  template<class From, class To>
172
  concept convertible-to-non-slicing = // exposition only
173
  convertible_to<From, To> &&
174
+ !uses-nonqualification-pointer-conversion<decay_t<From>, decay_t<To>>;
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  template<class T, class U, class V>
177
  concept pair-like-convertible-from = // exposition only
178
+ !range<T> && !is_reference_v<T> && pair-like<T> &&
179
  constructible_from<T, U, V> &&
180
  convertible-to-non-slicing<U, tuple_element_t<0, T>> &&
181
  convertible_to<V, tuple_element_t<1, T>>;
182
 
 
 
 
 
 
183
  template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
184
  sized_sentinel_for<S, I> ? subrange_kind::sized : subrange_kind::unsized>
185
  requires (K == subrange_kind::sized || !sized_sentinel_for<S, I>)
186
  class subrange : public view_interface<subrange<I, S, K>> {
187
  private:
188
  static constexpr bool StoreSize = // exposition only
189
  K == subrange_kind::sized && !sized_sentinel_for<S, I>;
190
  I begin_ = I(); // exposition only
191
  S end_ = S(); // exposition only
192
  make-unsigned-like-t<iter_difference_t<I>> size_ = 0; // exposition only; present only
193
+ // if StoreSize is true
194
  public:
195
+ subrange() requires default_initializable<I> = default;
196
 
197
  constexpr subrange(convertible-to-non-slicing<I> auto i, S s) requires (!StoreSize);
198
 
199
  constexpr subrange(convertible-to-non-slicing<I> auto i, S s,
200
  make-unsigned-like-t<iter_difference_t<I>> n)
201
  requires (K == subrange_kind::sized);
202
 
203
+ template<different-from<subrange> R>
204
  requires borrowed_range<R> &&
205
  convertible-to-non-slicing<iterator_t<R>, I> &&
206
  convertible_to<sentinel_t<R>, S>
207
  constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
208
 
209
  template<borrowed_range R>
210
  requires convertible-to-non-slicing<iterator_t<R>, I> &&
211
  convertible_to<sentinel_t<R>, S>
212
  constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
213
  requires (K == subrange_kind::sized)
214
+ : subrange{ranges::begin(r), ranges::end(r), n} {}
 
215
 
216
+ template<different-from<subrange> PairLike>
217
  requires pair-like-convertible-from<PairLike, const I&, const S&>
218
  constexpr operator PairLike() const;
219
 
220
  constexpr I begin() const requires copyable<I>;
221
  [[nodiscard]] constexpr I begin() requires (!copyable<I>);
 
238
 
239
  template<input_or_output_iterator I, sentinel_for<I> S>
240
  subrange(I, S, make-unsigned-like-t<iter_difference_t<I>>) ->
241
  subrange<I, S, subrange_kind::sized>;
242
 
 
 
 
 
 
 
 
243
  template<borrowed_range R>
244
  subrange(R&&) ->
245
  subrange<iterator_t<R>, sentinel_t<R>,
246
  (sized_range<R> || sized_sentinel_for<sentinel_t<R>, iterator_t<R>>)
247
  ? subrange_kind::sized : subrange_kind::unsized>;
248
 
249
  template<borrowed_range R>
250
  subrange(R&&, make-unsigned-like-t<range_difference_t<R>>) ->
251
  subrange<iterator_t<R>, sentinel_t<R>, subrange_kind::sized>;
 
 
 
 
 
 
 
 
 
 
 
 
252
  }
253
  ```
254
 
255
  #### Constructors and conversions <a id="range.subrange.ctor">[[range.subrange.ctor]]</a>
256
 
 
268
  make-unsigned-like-t<iter_difference_t<I>> n)
269
  requires (K == subrange_kind::sized);
270
  ```
271
 
272
  *Preconditions:* \[`i`, `s`) is a valid range, and
273
+ `n == `*`to-unsigned-like`*`(ranges::distance(i, s))` is `true`.
274
 
275
  *Effects:* Initializes *begin\_* with `std::move(i)` and *end\_* with
276
  `s`. If *StoreSize* is `true`, initializes *size\_* with `n`.
277
 
278
  [*Note 1*: Accepting the length of the range and storing it to later
279
  return from `size()` enables `subrange` to model `sized_range` even when
280
  it stores an iterator and sentinel that do not model
281
  `sized_sentinel_for`. — *end note*]
282
 
283
  ``` cpp
284
+ template<different-from<subrange> R>
285
  requires borrowed_range<R> &&
286
  convertible-to-non-slicing<iterator_t<R>, I> &&
287
  convertible_to<sentinel_t<R>, S>
288
  constexpr subrange(R&& r) requires (!StoreSize || sized_range<R>);
289
  ```
290
 
291
  *Effects:* Equivalent to:
292
 
293
+ - If *StoreSize* is `true`,
294
+ `subrange(r, static_cast<decltype(`*`size_`*`)>(ranges::size(r)))`.
295
+ - Otherwise, `subrange(ranges::begin(r), ranges::end(r))`.
296
 
297
  ``` cpp
298
+ template<different-from<subrange> PairLike>
299
  requires pair-like-convertible-from<PairLike, const I&, const S&>
300
  constexpr operator PairLike() const;
301
  ```
302
 
303
  *Effects:* Equivalent to: `return PairLike(`*`begin_`*`, `*`end_`*`);`
 
380
  constexpr subrange& advance(iter_difference_t<I> n);
381
  ```
382
 
383
  *Effects:* Equivalent to:
384
 
 
385
  ``` cpp
386
+ if constexpr (bidirectional_iterator<I>) {
387
+ if (n < 0) {
388
+ ranges::advance(begin_, n);
389
+ if constexpr (StoreSize)
390
+ size_ += to-unsigned-like(-n);
391
+ return *this;
392
+ }
393
+ }
394
+
395
  auto d = n - ranges::advance(begin_, n, end_);
396
+ if constexpr (StoreSize)
397
  size_ -= to-unsigned-like(d);
 
 
 
 
 
 
 
398
  return *this;
399
  ```
400
 
401
  ``` cpp
402
  template<size_t N, class I, class S, subrange_kind K>
403
+ requires ((N == 0 && copyable<I>) || N == 1)
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
  ```
 
416
  return r.end();
417
  ```
418
 
419
  ### Dangling iterator handling <a id="range.dangling">[[range.dangling]]</a>
420
 
421
+ The type `dangling` is used together with the template aliases
422
+ `borrowed_iterator_t` and `borrowed_subrange_t`. When an algorithm that
423
+ typically returns an iterator into, or a subrange of, a range argument
424
+ is called with an rvalue range argument that does not model
425
+ `borrowed_range` [[range.range]], the return value possibly refers to a
426
+ range whose lifetime has ended. In such cases, the type `dangling` is
427
+ returned instead of an iterator or subrange.
428
 
429
  ``` cpp
430
  namespace std::ranges {
431
  struct dangling {
432
  constexpr dangling() noexcept = default;
433
+ constexpr dangling(auto&&...) noexcept {}
 
434
  };
435
  }
436
  ```
437
 
438
  [*Example 1*:
 
442
  auto result1 = ranges::find(f(), 42); // #1
443
  static_assert(same_as<decltype(result1), ranges::dangling>);
444
  auto vec = f();
445
  auto result2 = ranges::find(vec, 42); // #2
446
  static_assert(same_as<decltype(result2), vector<int>::iterator>);
447
+ auto result3 = ranges::find(ranges::subrange{vec}, 42); // #3
448
  static_assert(same_as<decltype(result3), vector<int>::iterator>);
449
  ```
450
 
451
  The call to `ranges::find` at \#1 returns `ranges::dangling` since `f()`
452
+ is an rvalue `vector`; it is possible for the `vector` to be destroyed
453
  before a returned iterator is dereferenced. However, the calls at \#2
454
  and \#3 both return iterators since the lvalue `vec` and specializations
455
  of `subrange` model `borrowed_range`.
456
 
457
  — *end example*]
458
 
459
+ For a type `R` that models `range`:
460
+
461
+ - if `R` models `borrowed_range`, then `borrowed_iterator_t<R>` denotes
462
+ `iterator_t<R>`, and `borrowed_subrange_t<R>` denotes
463
+ `subrange<iterator_t<R>>`;
464
+ - otherwise, both `borrowed_iterator_t<R>` and `borrowed_subrange_t<R>`
465
+ denote `dangling`.
466
+
467
+ ### Class template `elements_of` <a id="range.elementsof">[[range.elementsof]]</a>
468
+
469
+ Specializations of `elements_of` encapsulate a range and act as a tag in
470
+ overload sets to disambiguate when a range should be treated as a
471
+ sequence rather than a single value.
472
+
473
+ [*Example 1*:
474
+
475
+ ``` cpp
476
+ template<bool YieldElements>
477
+ generator<any> f(ranges::input_range auto&& r) {
478
+ if constexpr (YieldElements)
479
+ co_yield ranges::elements_of(r); // yield each element of r
480
+ else
481
+ co_yield r; // yield r as a single value
482
+ }
483
+ ```
484
+
485
+ — *end example*]
486
+
487
+ ``` cpp
488
+ namespace std::ranges {
489
+ template<range R, class Allocator = allocator<byte>>
490
+ struct elements_of {
491
+ [[no_unique_address]] R range;
492
+ [[no_unique_address]] Allocator allocator = Allocator();
493
+ };
494
+
495
+ template<class R, class Allocator = allocator<byte>>
496
+ elements_of(R&&, Allocator = Allocator()) -> elements_of<R&&, Allocator>;
497
+ }
498
+ ```
499
+
500
+ ### Range conversions <a id="range.utility.conv">[[range.utility.conv]]</a>
501
+
502
+ #### General <a id="range.utility.conv.general">[[range.utility.conv.general]]</a>
503
+
504
+ The range conversion functions construct an object (usually a container)
505
+ from a range, by using a constructor taking a range, a `from_range_t`
506
+ tagged constructor, or a constructor taking a pair of iterators, or by
507
+ inserting each element of the range into the default-constructed object.
508
+
509
+ `ranges::to` is applied recursively, allowing the conversion of a range
510
+ of ranges.
511
+
512
+ [*Example 1*:
513
+
514
+ ``` cpp
515
+ string_view str = "the quick brown fox";
516
+ auto words = views::split(str, ' ') | to<vector<string>>();
517
+ // words is vector<string>{"the", "quick", "brown", "fox"}
518
+ ```
519
+
520
+ — *end example*]
521
+
522
+ Let *`reservable-container`* be defined as follows:
523
+
524
+ ``` cpp
525
+ template<class Container>
526
+ constexpr bool reservable-container = // exposition only
527
+ sized_range<Container> &&
528
+ requires(Container& c, range_size_t<Container> n) {
529
+ c.reserve(n);
530
+ { c.capacity() } -> same_as<decltype(n)>;
531
+ { c.max_size() } -> same_as<decltype(n)>;
532
+ };
533
+ ```
534
+
535
+ Let *`container-insertable`* be defined as follows:
536
+
537
+ ``` cpp
538
+ template<class Container, class Ref>
539
+ constexpr bool container-insertable = // exposition only
540
+ requires(Container& c, Ref&& ref) {
541
+ requires (requires { c.push_back(std::forward<Ref>(ref)); } ||
542
+ requires { c.insert(c.end(), std::forward<Ref>(ref)); });
543
+ };
544
+ ```
545
+
546
+ Let *`container-inserter`* be defined as follows:
547
+
548
+ ``` cpp
549
+ template<class Ref, class Container>
550
+ constexpr auto container-inserter(Container& c) { // exposition only
551
+ if constexpr (requires { c.push_back(declval<Ref>()); })
552
+ return back_inserter(c);
553
+ else
554
+ return inserter(c, c.end());
555
+ }
556
+ ```
557
+
558
+ #### `ranges::to` <a id="range.utility.conv.to">[[range.utility.conv.to]]</a>
559
+
560
+ ``` cpp
561
+ template<class C, input_range R, class... Args> requires (!view<C>)
562
+ constexpr C to(R&& r, Args&&... args);
563
+ ```
564
+
565
+ *Mandates:* `C` is a cv-unqualified class type.
566
+
567
+ *Returns:* An object of type `C` constructed from the elements of `r` in
568
+ the following manner:
569
+
570
+ - If `C` does not satisfy `input_range` or
571
+ `convertible_to<range_reference_t<R>, range_value_t<C>>` is `true`:
572
+ - If `constructible_from<C, R, Args...>` is `true`:
573
+ ``` cpp
574
+ C(std::forward<R>(r), std::forward<Args>(args)...)
575
+ ```
576
+ - Otherwise, if `constructible_from<C, from_range_t, R, Args...>` is
577
+ `true`:
578
+ ``` cpp
579
+ C(from_range, std::forward<R>(r), std::forward<Args>(args)...)
580
+ ```
581
+ - Otherwise, if
582
+ - `common_range<R>` is `true`,
583
+ - the *qualified-id*
584
+ `iterator_traits<iterator_t<R>>::iterator_category` is valid and
585
+ denotes a type that models `derived_from<input_iterator_tag>`, and
586
+ - `constructible_from<C, iterator_t<R>, sentinel_t<R>, Args...>` is
587
+ `true`:
588
+
589
+ ``` cpp
590
+ C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)
591
+ ```
592
+ - Otherwise, if
593
+ - `constructible_from<C, Args...>` is `true`, and
594
+ - *`container-insertable`*`<C, range_reference_t<R>>` is `true`:
595
+
596
+ ``` cpp
597
+ C c(std::forward<Args>(args)...);
598
+ if constexpr (sized_range<R> && reservable-container<C>)
599
+ c.reserve(static_cast<range_size_t<C>>(ranges::size(r)));
600
+ ranges::copy(r, container-inserter<range_reference_t<R>>(c));
601
+ ```
602
+ - Otherwise, if `input_range<range_reference_t<R>>` is `true`:
603
+ ``` cpp
604
+ to<C>(r | views::transform([](auto&& elem) {
605
+ return to<range_value_t<C>>(std::forward<decltype(elem)>(elem));
606
+ }), std::forward<Args>(args)...);
607
+ ```
608
+ - Otherwise, the program is ill-formed.
609
+
610
+ ``` cpp
611
+ template<template<class...> class C, input_range R, class... Args>
612
+ constexpr auto to(R&& r, Args&&... args);
613
+ ```
614
+
615
+ Let *input-iterator* be an exposition-only type:
616
+
617
+ ``` cpp
618
+ struct input-iterator { // exposition only
619
+ using iterator_category = input_iterator_tag;
620
+ using value_type = range_value_t<R>;
621
+ using difference_type = ptrdiff_t;
622
+ using pointer = add_pointer_t<range_reference_t<R>>;
623
+ using reference = range_reference_t<R>;
624
+ reference operator*() const;
625
+ pointer operator->() const;
626
+ input-iterator& operator++();
627
+ input-iterator operator++(int);
628
+ bool operator==(const input-iterator&) const;
629
+ };
630
+ ```
631
+
632
+ [*Note 1*: *input-iterator* meets the syntactic requirements of
633
+ *Cpp17InputIterator*. — *end note*]
634
+
635
+ Let *`DEDUCE_EXPR`* be defined as follows:
636
+
637
+ - `C(declval<R>(), declval<Args>()...)` if that is a valid expression,
638
+ - otherwise, `C(from_range, declval<R>(), declval<Args>()...)` if that
639
+ is a valid expression,
640
+ - otherwise,
641
+ ``` cpp
642
+ C(declval<input-iterator>(), declval<input-iterator>(), declval<Args>()...)
643
+ ```
644
+
645
+ if that is a valid expression,
646
+ - otherwise, the program is ill-formed.
647
+
648
+ *Returns:*
649
+ `to<decltype(`*`DEDUCE_EXPR`*`)>(std::forward<R>(r), std::forward<Args>(args)...)`.
650
+
651
+ #### `ranges::to` adaptors <a id="range.utility.conv.adaptors">[[range.utility.conv.adaptors]]</a>
652
+
653
+ ``` cpp
654
+ template<class C, class... Args> requires (!view<C>)
655
+ constexpr auto to(Args&&... args);
656
+ template<template<class...> class C, class... Args>
657
+ constexpr auto to(Args&&... args);
658
+ ```
659
+
660
+ *Mandates:* For the first overload, `C` is a cv-unqualified class type.
661
+
662
+ *Returns:* A range adaptor closure object [[range.adaptor.object]] `f`
663
+ that is a perfect forwarding call
664
+ wrapper [[term.perfect.forwarding.call.wrapper]] with the following
665
+ properties:
666
+
667
+ - It has no target object.
668
+ - Its bound argument entities `bound_args` consist of objects of types
669
+ `decay_t<Args>...` direct-non-list-initialized with
670
+ `std::forward<Args>(args)...`, respectively.
671
+ - Its call pattern is `to<C>(r, bound_args...)`, where `r` is the
672
+ argument used in a function call expression of `f`.
673
+