From Jason Turner

[range.split]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmppim4s85_/{from.md → to.md} +416 -0
tmp/tmppim4s85_/{from.md → to.md} RENAMED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Split view <a id="range.split">[[range.split]]</a>
2
+
3
+ #### Overview <a id="range.split.overview">[[range.split.overview]]</a>
4
+
5
+ `split_view` takes a `view` and a delimiter, and splits the `view` into
6
+ subranges on the delimiter. The delimiter can be a single element or a
7
+ `view` of elements.
8
+
9
+ The name `views::split` denotes a range adaptor object
10
+ [[range.adaptor.object]]. Given subexpressions `E` and `F`, the
11
+ expression `views::split(E, F)` is expression-equivalent to
12
+ `split_view{E, F}`.
13
+
14
+ [*Example 1*:
15
+
16
+ ``` cpp
17
+ string str{"the quick brown fox"};
18
+ split_view sentence{str, ' '};
19
+ for (auto word : sentence) {
20
+ for (char ch : word)
21
+ cout << ch;
22
+ cout << '*';
23
+ }
24
+ // The above prints: the*quick*brown*fox*
25
+ ```
26
+
27
+ — *end example*]
28
+
29
+ #### Class template `split_view` <a id="range.split.view">[[range.split.view]]</a>
30
+
31
+ ``` cpp
32
+ namespace std::ranges {
33
+ template<auto> struct require-constant; // exposition only
34
+
35
+ template<class R>
36
+ concept tiny-range = // exposition only
37
+ sized_range<R> &&
38
+ requires { typename require-constant<remove_reference_t<R>::size()>; } &&
39
+ (remove_reference_t<R>::size() <= 1);
40
+
41
+ template<input_range V, forward_range Pattern>
42
+ requires view<V> && view<Pattern> &&
43
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
44
+ (forward_range<V> || tiny-range<Pattern>)
45
+ class split_view : public view_interface<split_view<V, Pattern>> {
46
+ private:
47
+ V base_ = V(); // exposition only
48
+ Pattern pattern_ = Pattern(); // exposition only
49
+ iterator_t<V> current_ = iterator_t<V>(); // exposition only, present only if !forward_range<V>
50
+ // [range.split.outer], class template split_view::outer-iterator
51
+ template<bool> struct outer-iterator; // exposition only
52
+ // [range.split.inner], class template split_view::inner-iterator
53
+ template<bool> struct inner-iterator; // exposition only
54
+ public:
55
+ split_view() = default;
56
+ constexpr split_view(V base, Pattern pattern);
57
+
58
+ template<input_range R>
59
+ requires constructible_from<V, views::all_t<R>> &&
60
+ constructible_from<Pattern, single_view<range_value_t<R>>>
61
+ constexpr split_view(R&& r, range_value_t<R> e);
62
+
63
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
64
+ constexpr V base() && { return std::move(base_); }
65
+
66
+ constexpr auto begin() {
67
+ if constexpr (forward_range<V>)
68
+ return outer-iterator<simple-view<V>>{*this, ranges::begin(base_)};
69
+ else {
70
+ current_ = ranges::begin(base_);
71
+ return outer-iterator<false>{*this};
72
+ }
73
+ }
74
+
75
+ constexpr auto begin() const requires forward_range<V> && forward_range<const V> {
76
+ return outer-iterator<true>{*this, ranges::begin(base_)};
77
+ }
78
+
79
+ constexpr auto end() requires forward_range<V> && common_range<V> {
80
+ return outer-iterator<simple-view<V>>{*this, ranges::end(base_)};
81
+ }
82
+
83
+ constexpr auto end() const {
84
+ if constexpr (forward_range<V> && forward_range<const V> && common_range<const V>)
85
+ return outer-iterator<true>{*this, ranges::end(base_)};
86
+ else
87
+ return default_sentinel;
88
+ }
89
+ };
90
+
91
+ template<class R, class P>
92
+ split_view(R&&, P&&) -> split_view<views::all_t<R>, views::all_t<P>>;
93
+
94
+ template<input_range R>
95
+ split_view(R&&, range_value_t<R>)
96
+ -> split_view<views::all_t<R>, single_view<range_value_t<R>>>;
97
+ }
98
+ ```
99
+
100
+ ``` cpp
101
+ constexpr split_view(V base, Pattern pattern);
102
+ ```
103
+
104
+ *Effects:* Initializes *base\_* with `std::move(base)`, and *pattern\_*
105
+ with `std::move(pattern)`.
106
+
107
+ ``` cpp
108
+ template<input_range R>
109
+ requires constructible_from<V, views::all_t<R>> &&
110
+ constructible_from<Pattern, single_view<range_value_t<R>>>
111
+ constexpr split_view(R&& r, range_value_t<R> e);
112
+ ```
113
+
114
+ *Effects:* Initializes *base\_* with `views::all(std::forward<R>(r))`,
115
+ and *pattern\_* with `single_view{std::move(e)}`.
116
+
117
+ #### Class template `split_view::outer-iterator` <a id="range.split.outer">[[range.split.outer]]</a>
118
+
119
+ ``` cpp
120
+ namespace std::ranges {
121
+ template<input_range V, forward_range Pattern>
122
+ requires view<V> && view<Pattern> &&
123
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
124
+ (forward_range<V> || tiny-range<Pattern>)
125
+ template<bool Const>
126
+ struct split_view<V, Pattern>::outer-iterator {
127
+ private:
128
+ using Parent = // exposition only
129
+ conditional_t<Const, const split_view, split_view>;
130
+ using Base = // exposition only
131
+ conditional_t<Const, const V, V>;
132
+ Parent* parent_ = nullptr; // exposition only
133
+ iterator_t<Base> current_ = // exposition only, present only if V models forward_range
134
+ iterator_t<Base>();
135
+
136
+ public:
137
+ using iterator_concept =
138
+ conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
139
+ using iterator_category = input_iterator_tag;
140
+ // [range.split.outer.value], class split_view::outer-iterator::value_type
141
+ struct value_type;
142
+ using difference_type = range_difference_t<Base>;
143
+
144
+ outer-iterator() = default;
145
+ constexpr explicit outer-iterator(Parent& parent)
146
+ requires (!forward_range<Base>);
147
+ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
148
+ requires forward_range<Base>;
149
+ constexpr outer-iterator(outer-iterator<!Const> i)
150
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
151
+
152
+ constexpr value_type operator*() const;
153
+
154
+ constexpr outer-iterator& operator++();
155
+ constexpr decltype(auto) operator++(int) {
156
+ if constexpr (forward_range<Base>) {
157
+ auto tmp = *this;
158
+ ++*this;
159
+ return tmp;
160
+ } else
161
+ ++*this;
162
+ }
163
+
164
+ friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
165
+ requires forward_range<Base>;
166
+
167
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
168
+ };
169
+ }
170
+ ```
171
+
172
+ Many of the following specifications refer to the notional member
173
+ *current* of *`outer-iterator`*. *current* is equivalent to *`current_`*
174
+ if `V` models `forward_range`, and `parent_->current_` otherwise.
175
+
176
+ ``` cpp
177
+ constexpr explicit outer-iterator(Parent& parent)
178
+ requires (!forward_range<Base>);
179
+ ```
180
+
181
+ *Effects:* Initializes *parent\_* with `addressof(parent)`.
182
+
183
+ ``` cpp
184
+ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
185
+ requires forward_range<Base>;
186
+ ```
187
+
188
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and
189
+ *current\_* with `std::move(current)`.
190
+
191
+ ``` cpp
192
+ constexpr outer-iterator(outer-iterator<!Const> i)
193
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
194
+ ```
195
+
196
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *current\_*
197
+ with `std::move(i.`*`current_`*`)`.
198
+
199
+ ``` cpp
200
+ constexpr value_type operator*() const;
201
+ ```
202
+
203
+ *Effects:* Equivalent to: `return value_type{*this};`
204
+
205
+ ``` cpp
206
+ constexpr outer-iterator& operator++();
207
+ ```
208
+
209
+ *Effects:* Equivalent to:
210
+
211
+ ``` cpp
212
+ const auto end = ranges::end(parent_->base_);
213
+ if (current == end) return *this;
214
+ const auto [pbegin, pend] = subrange{parent_->pattern_};
215
+ if (pbegin == pend) ++current;
216
+ else {
217
+ do {
218
+ auto [b, p] = ranges::mismatch(std::move(current), end, pbegin, pend);
219
+ current = std::move(b);
220
+ if (p == pend) {
221
+ break; // The pattern matched; skip it
222
+ }
223
+ } while (++current != end);
224
+ }
225
+ return *this;
226
+ ```
227
+
228
+ ``` cpp
229
+ friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
230
+ requires forward_range<Base>;
231
+ ```
232
+
233
+ *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`current_`*`;`
234
+
235
+ ``` cpp
236
+ friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
237
+ ```
238
+
239
+ *Effects:* Equivalent to:
240
+ `return x.`*`current`*` == ranges::end(x.`*`parent_`*`->`*`base_`*`);`
241
+
242
+ #### Class `split_view::outer-iterator::value_type` <a id="range.split.outer.value">[[range.split.outer.value]]</a>
243
+
244
+ ``` cpp
245
+ namespace std::ranges {
246
+ template<input_range V, forward_range Pattern>
247
+ requires view<V> && view<Pattern> &&
248
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
249
+ (forward_range<V> || tiny-range<Pattern>)
250
+ template<bool Const>
251
+ struct split_view<V, Pattern>::outer-iterator<Const>::value_type
252
+ : view_interface<value_type> {
253
+ private:
254
+ outer-iterator i_ = outer-iterator(); // exposition only
255
+ public:
256
+ value_type() = default;
257
+ constexpr explicit value_type(outer-iterator i);
258
+
259
+ constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
260
+ constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
261
+ constexpr default_sentinel_t end() const;
262
+ };
263
+ }
264
+ ```
265
+
266
+ ``` cpp
267
+ constexpr explicit value_type(outer-iterator i);
268
+ ```
269
+
270
+ *Effects:* Initializes *i\_* with `std::move(i)`.
271
+
272
+ ``` cpp
273
+ constexpr inner-iterator<Const> begin() const requires copyable<outer-iterator>;
274
+ ```
275
+
276
+ *Effects:* Equivalent to:
277
+ `return `*`inner-iterator`*`<Const>{`*`i_`*`};`
278
+
279
+ ``` cpp
280
+ constexpr inner-iterator<Const> begin() requires (!copyable<outer-iterator>);
281
+ ```
282
+
283
+ *Effects:* Equivalent to:
284
+ `return `*`inner-iterator`*`<Const>{std::move(`*`i_`*`)};`
285
+
286
+ ``` cpp
287
+ constexpr default_sentinel_t end() const;
288
+ ```
289
+
290
+ *Effects:* Equivalent to: `return default_sentinel;`
291
+
292
+ #### Class template `split_view::inner-iterator` <a id="range.split.inner">[[range.split.inner]]</a>
293
+
294
+ ``` cpp
295
+ namespace std::ranges {
296
+ template<input_range V, forward_range Pattern>
297
+ requires view<V> && view<Pattern> &&
298
+ indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
299
+ (forward_range<V> || tiny-range<Pattern>)
300
+ template<bool Const>
301
+ struct split_view<V, Pattern>::inner-iterator {
302
+ private:
303
+ using Base = conditional_t<Const, const V, V>; // exposition only
304
+ outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
305
+ bool incremented_ = false; // exposition only
306
+ public:
307
+ using iterator_concept = typename outer-iterator<Const>::iterator_concept;
308
+ using iterator_category = see below;
309
+ using value_type = range_value_t<Base>;
310
+ using difference_type = range_difference_t<Base>;
311
+
312
+ inner-iterator() = default;
313
+ constexpr explicit inner-iterator(outer-iterator<Const> i);
314
+
315
+ constexpr decltype(auto) operator*() const { return *i_.current; }
316
+
317
+ constexpr inner-iterator& operator++();
318
+ constexpr decltype(auto) operator++(int) {
319
+ if constexpr (forward_range<V>) {
320
+ auto tmp = *this;
321
+ ++*this;
322
+ return tmp;
323
+ } else
324
+ ++*this;
325
+ }
326
+
327
+ friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y)
328
+ requires forward_range<Base>;
329
+
330
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
331
+
332
+ friend constexpr decltype(auto) iter_move(const inner-iterator& i)
333
+ noexcept(noexcept(ranges::iter_move(i.i_.current))) {
334
+ return ranges::iter_move(i.i_.current);
335
+ }
336
+
337
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
338
+ noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
339
+ requires indirectly_swappable<iterator_t<Base>>;
340
+ };
341
+ }
342
+ ```
343
+
344
+ The *typedef-name* `iterator_category` denotes:
345
+
346
+ - `forward_iterator_tag` if
347
+ `iterator_traits<iterator_t<Base>>::iterator_category` models
348
+ `derived_from<forward_iterator_tag>`;
349
+ - otherwise, `iterator_traits<iterator_t<Base>>::iterator_category`.
350
+
351
+ ``` cpp
352
+ constexpr explicit inner-iterator(outer-iterator<Const> i);
353
+ ```
354
+
355
+ *Effects:* Initializes *i\_* with `std::move(i)`.
356
+
357
+ ``` cpp
358
+ constexpr inner-iterator& operator++();
359
+ ```
360
+
361
+ *Effects:* Equivalent to:
362
+
363
+ ``` cpp
364
+ incremented_ = true;
365
+ if constexpr (!forward_range<Base>) {
366
+ if constexpr (Pattern::size() == 0) {
367
+ return *this;
368
+ }
369
+ }
370
+ ++i_.current;
371
+ return *this;
372
+ ```
373
+
374
+ ``` cpp
375
+ friend constexpr bool operator==(const inner-iterator& x, const inner-iterator& y)
376
+ requires forward_range<Base>;
377
+ ```
378
+
379
+ *Effects:* Equivalent to:
380
+ `return x.`*`i_`*`.`*`current`*` == y.`*`i_`*`.`*`current`*`;`
381
+
382
+ ``` cpp
383
+ friend constexpr bool operator==(const inner-iterator& x, default_sentinel_t);
384
+ ```
385
+
386
+ *Effects:* Equivalent to:
387
+
388
+ ``` cpp
389
+ auto [pcur, pend] = subrange{x.i_.parent_->pattern_};
390
+ auto end = ranges::end(x.i_.parent_->base_);
391
+ if constexpr (tiny-range<Pattern>) {
392
+ const auto & cur = x.i_.current;
393
+ if (cur == end) return true;
394
+ if (pcur == pend) return x.incremented_;
395
+ return *cur == *pcur;
396
+ } else {
397
+ auto cur = x.i_.current;
398
+ if (cur == end) return true;
399
+ if (pcur == pend) return x.incremented_;
400
+ do {
401
+ if (*cur != *pcur) return false;
402
+ if (++pcur == pend) return true;
403
+ } while (++cur != end);
404
+ return false;
405
+ }
406
+ ```
407
+
408
+ ``` cpp
409
+ friend constexpr void iter_swap(const inner-iterator& x, const inner-iterator& y)
410
+ noexcept(noexcept(ranges::iter_swap(x.i_.current, y.i_.current)))
411
+ requires indirectly_swappable<iterator_t<Base>>;
412
+ ```
413
+
414
+ *Effects:* Equivalent to
415
+ `ranges::iter_swap(x.`*`i_`*`.`*`current`*`, y.`*`i_`*`.`*`current`*`)`.
416
+