From Jason Turner

[range.join]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp4c5o9n14/{from.md → to.md} +394 -0
tmp/tmp4c5o9n14/{from.md → to.md} RENAMED
@@ -0,0 +1,394 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Join view <a id="range.join">[[range.join]]</a>
2
+
3
+ #### Overview <a id="range.join.overview">[[range.join.overview]]</a>
4
+
5
+ `join_view` flattens a `view` of ranges into a `view`.
6
+
7
+ The name `views::join` denotes a range adaptor object
8
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
9
+ `views::join(E)` is expression-equivalent to `join_view{E}`.
10
+
11
+ [*Example 1*:
12
+
13
+ ``` cpp
14
+ vector<string> ss{"hello", " ", "world", "!"};
15
+ join_view greeting{ss};
16
+ for (char ch : greeting)
17
+ cout << ch; // prints: hello world!
18
+ ```
19
+
20
+ — *end example*]
21
+
22
+ #### Class template `join_view` <a id="range.join.view">[[range.join.view]]</a>
23
+
24
+ ``` cpp
25
+ namespace std::ranges {
26
+ template<input_range V>
27
+ requires view<V> && input_range<range_reference_t<V>> &&
28
+ (is_reference_v<range_reference_t<V>> ||
29
+ view<range_value_t<V>>)
30
+ class join_view : public view_interface<join_view<V>> {
31
+ private:
32
+ using InnerRng = // exposition only
33
+ range_reference_t<V>;
34
+ // [range.join.iterator], class template join_view::iterator
35
+ template<bool Const>
36
+ struct iterator; // exposition only
37
+ // [range.join.sentinel], class template join_view::sentinel
38
+ template<bool Const>
39
+ struct sentinel; // exposition only
40
+
41
+ V base_ = V(); // exposition only
42
+ views::all_t<InnerRng> inner_ = // exposition only, present only when !is_reference_v<InnerRng>
43
+ views::all_t<InnerRng>();
44
+ public:
45
+ join_view() = default;
46
+ constexpr explicit join_view(V base);
47
+
48
+ constexpr V base() const& requires copy_constructible<V> { return base_; }
49
+ constexpr V base() && { return std::move(base_); }
50
+
51
+ constexpr auto begin() {
52
+ constexpr bool use_const = simple-view<V> &&
53
+ is_reference_v<range_reference_t<V>>;
54
+ return iterator<use_const>{*this, ranges::begin(base_)};
55
+ }
56
+
57
+ constexpr auto begin() const
58
+ requires input_range<const V> &&
59
+ is_reference_v<range_reference_t<const V>> {
60
+ return iterator<true>{*this, ranges::begin(base_)};
61
+ }
62
+
63
+ constexpr auto end() {
64
+ if constexpr (forward_range<V> &&
65
+ is_reference_v<InnerRng> && forward_range<InnerRng> &&
66
+ common_range<V> && common_range<InnerRng>)
67
+ return iterator<simple-view<V>>{*this, ranges::end(base_)};
68
+ else
69
+ return sentinel<simple-view<V>>{*this};
70
+ }
71
+
72
+ constexpr auto end() const
73
+ requires input_range<const V> &&
74
+ is_reference_v<range_reference_t<const V>> {
75
+ if constexpr (forward_range<const V> &&
76
+ is_reference_v<range_reference_t<const V>> &&
77
+ forward_range<range_reference_t<const V>> &&
78
+ common_range<const V> &&
79
+ common_range<range_reference_t<const V>>)
80
+ return iterator<true>{*this, ranges::end(base_)};
81
+ else
82
+ return sentinel<true>{*this};
83
+ }
84
+ };
85
+
86
+ template<class R>
87
+ explicit join_view(R&&) -> join_view<views::all_t<R>>;
88
+ }
89
+ ```
90
+
91
+ ``` cpp
92
+ constexpr explicit join_view(V base);
93
+ ```
94
+
95
+ *Effects:* Initializes *base\_* with `std::move(base)`.
96
+
97
+ #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
98
+
99
+ ``` cpp
100
+ namespace std::ranges {
101
+ template<input_range V>
102
+ requires view<V> && input_range<range_reference_t<V>> &&
103
+ (is_reference_v<range_reference_t<V>> ||
104
+ view<range_value_t<V>>)
105
+ template<bool Const>
106
+ struct join_view<V>::iterator {
107
+ private:
108
+ using Parent = // exposition only
109
+ conditional_t<Const, const join_view, join_view>;
110
+ using Base = conditional_t<Const, const V, V>; // exposition only
111
+
112
+ static constexpr bool ref-is-glvalue = // exposition only
113
+ is_reference_v<range_reference_t<Base>>;
114
+
115
+ iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only
116
+ iterator_t<range_reference_t<Base>> inner_ = // exposition only
117
+ iterator_t<range_reference_t<Base>>();
118
+ Parent* parent_ = nullptr; // exposition only
119
+
120
+ constexpr void satisfy(); // exposition only
121
+ public:
122
+ using iterator_concept = see below;
123
+ using iterator_category = see below;
124
+ using value_type = range_value_t<range_reference_t<Base>>;
125
+ using difference_type = see below;
126
+
127
+ iterator() = default;
128
+ constexpr iterator(Parent& parent, iterator_t<Base> outer);
129
+ constexpr iterator(iterator<!Const> i)
130
+ requires Const &&
131
+ convertible_to<iterator_t<V>, iterator_t<Base>> &&
132
+ convertible_to<iterator_t<InnerRng>,
133
+ iterator_t<range_reference_t<Base>>>;
134
+
135
+ constexpr decltype(auto) operator*() const { return *inner_; }
136
+
137
+ constexpr iterator_t<Base> operator->() const
138
+ requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
139
+
140
+ constexpr iterator& operator++();
141
+ constexpr void operator++(int);
142
+ constexpr iterator operator++(int)
143
+ requires ref-is-glvalue && forward_range<Base> &&
144
+ forward_range<range_reference_t<Base>>;
145
+
146
+ constexpr iterator& operator--()
147
+ requires ref-is-glvalue && bidirectional_range<Base> &&
148
+ bidirectional_range<range_reference_t<Base>> &&
149
+ common_range<range_reference_t<Base>>;
150
+
151
+ constexpr iterator operator--(int)
152
+ requires ref-is-glvalue && bidirectional_range<Base> &&
153
+ bidirectional_range<range_reference_t<Base>> &&
154
+ common_range<range_reference_t<Base>>;
155
+
156
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
157
+ requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
158
+ equality_comparable<iterator_t<range_reference_t<Base>>>;
159
+
160
+ friend constexpr decltype(auto) iter_move(const iterator& i)
161
+ noexcept(noexcept(ranges::iter_move(i.inner_))) {
162
+ return ranges::iter_move(i.inner_);
163
+ }
164
+
165
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
166
+ noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
167
+ };
168
+ }
169
+ ```
170
+
171
+ `iterator::iterator_concept` is defined as follows:
172
+
173
+ - If *`ref-is-glvalue`* is `true` and *`Base`* and
174
+ `range_reference_t<Base>` each model `bidirectional_range`, then
175
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
176
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
177
+ `range_reference_t<Base>` each model , then `iterator_concept` denotes
178
+ `forward_iterator_tag`.
179
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
180
+
181
+ `iterator::iterator_category` is defined as follows:
182
+
183
+ - Let *OUTERC* denote
184
+ `iterator_traits<iterator_t<Base>>::iterator_category`, and let
185
+ *INNERC* denote
186
+ `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
187
+ - If *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC* each model
188
+ `derived_from<bidirectional_iterator_tag>`, `iterator_category`
189
+ denotes `bidirectional_iterator_tag`.
190
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC*
191
+ each model `derived_from<forward_iterator_tag>`, `iterator_category`
192
+ denotes `forward_iterator_tag`.
193
+ - Otherwise, if *OUTERC* and *INNERC* each model
194
+ `derived_from<input_iterator_tag>`, `iterator_category` denotes
195
+ `input_iterator_tag`.
196
+ - Otherwise, `iterator_category` denotes `output_iterator_tag`.
197
+
198
+ `iterator::difference_type` denotes the type:
199
+
200
+ ``` cpp
201
+ common_type_t<
202
+ range_difference_t<Base>,
203
+ range_difference_t<range_reference_t<Base>>>
204
+ ```
205
+
206
+ `join_view` iterators use the *`satisfy`* function to skip over empty
207
+ inner ranges.
208
+
209
+ ``` cpp
210
+ constexpr void satisfy(); // exposition only
211
+ ```
212
+
213
+ *Effects:* Equivalent to:
214
+
215
+ ``` cpp
216
+ auto update_inner = [this](range_reference_t<Base> x) -> auto& {
217
+ if constexpr (ref-is-glvalue) // x is a reference
218
+ return x;
219
+ else
220
+ return (parent_->inner_ = views::all(std::move(x)));
221
+ };
222
+
223
+ for (; outer_ != ranges::end(parent_->base_); ++outer_) {
224
+ auto& inner = update_inner(*outer_);
225
+ inner_ = ranges::begin(inner);
226
+ if (inner_ != ranges::end(inner))
227
+ return;
228
+ }
229
+ if constexpr (ref-is-glvalue)
230
+ inner_ = iterator_t<range_reference_t<Base>>();
231
+ ```
232
+
233
+ ``` cpp
234
+ constexpr iterator(Parent& parent, iterator_t<Base> outer);
235
+ ```
236
+
237
+ *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
238
+ with `addressof(parent)`; then calls *`satisfy`*`()`.
239
+
240
+ ``` cpp
241
+ constexpr iterator(iterator<!Const> i)
242
+ requires Const &&
243
+ convertible_to<iterator_t<V>, iterator_t<Base>> &&
244
+ convertible_to<iterator_t<InnerRng>,
245
+ iterator_t<range_reference_t<Base>>>;
246
+ ```
247
+
248
+ *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
249
+ *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
250
+ `i.`*`parent_`*.
251
+
252
+ ``` cpp
253
+ constexpr iterator_t<Base> operator->() const
254
+ requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
255
+ ```
256
+
257
+ *Effects:* Equivalent to `return `*`inner_`*`;`
258
+
259
+ ``` cpp
260
+ constexpr iterator& operator++();
261
+ ```
262
+
263
+ Let *`inner-range`* be:
264
+
265
+ - If *ref-is-glvalue* is `true`, `*`*`outer_`*.
266
+ - Otherwise, *`parent_`*`->`*`inner_`*.
267
+
268
+ *Effects:* Equivalent to:
269
+
270
+ ``` cpp
271
+ auto&& inner_rng = inner-range;
272
+ if (++inner_ == ranges::end(inner_rng)) {
273
+ ++outer_;
274
+ satisfy();
275
+ }
276
+ return *this;
277
+ ```
278
+
279
+ ``` cpp
280
+ constexpr void operator++(int);
281
+ ```
282
+
283
+ *Effects:* Equivalent to: `++*this`.
284
+
285
+ ``` cpp
286
+ constexpr iterator operator++(int)
287
+ requires ref-is-glvalue && forward_range<Base> &&
288
+ forward_range<range_reference_t<Base>>;
289
+ ```
290
+
291
+ *Effects:* Equivalent to:
292
+
293
+ ``` cpp
294
+ auto tmp = *this;
295
+ ++*this;
296
+ return tmp;
297
+ ```
298
+
299
+ ``` cpp
300
+ constexpr iterator& operator--()
301
+ requires ref-is-glvalue && bidirectional_range<Base> &&
302
+ bidirectional_range<range_reference_t<Base>> &&
303
+ common_range<range_reference_t<Base>>;
304
+ ```
305
+
306
+ *Effects:* Equivalent to:
307
+
308
+ ``` cpp
309
+ if (outer_ == ranges::end(parent_->base_))
310
+ inner_ = ranges::end(*--outer_);
311
+ while (inner_ == ranges::begin(*outer_))
312
+ inner_ = ranges::end(*--outer_);
313
+ --inner_;
314
+ return *this;
315
+ ```
316
+
317
+ ``` cpp
318
+ constexpr iterator operator--(int)
319
+ requires ref-is-glvalue && bidirectional_range<Base> &&
320
+ bidirectional_range<range_reference_t<Base>> &&
321
+ common_range<range_reference_t<Base>>;
322
+ ```
323
+
324
+ *Effects:* Equivalent to:
325
+
326
+ ``` cpp
327
+ auto tmp = *this;
328
+ --*this;
329
+ return tmp;
330
+ ```
331
+
332
+ ``` cpp
333
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
334
+ requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
335
+ equality_comparable<iterator_t<range_reference_t<Base>>>;
336
+ ```
337
+
338
+ *Effects:* Equivalent to:
339
+ `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
340
+
341
+ ``` cpp
342
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
343
+ noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
344
+ ```
345
+
346
+ *Effects:* Equivalent to:
347
+ `return ranges::iter_swap(x.`*`inner_`*`, y.`*`inner_`*`);`
348
+
349
+ #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
350
+
351
+ ``` cpp
352
+ namespace std::ranges {
353
+ template<input_range V>
354
+ requires view<V> && input_range<range_reference_t<V>> &&
355
+ (is_reference_v<range_reference_t<V>> ||
356
+ view<range_value_t<V>>)
357
+ template<bool Const>
358
+ struct join_view<V>::sentinel {
359
+ private:
360
+ using Parent = // exposition only
361
+ conditional_t<Const, const join_view, join_view>;
362
+ using Base = conditional_t<Const, const V, V>; // exposition only
363
+ sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
364
+ public:
365
+ sentinel() = default;
366
+
367
+ constexpr explicit sentinel(Parent& parent);
368
+ constexpr sentinel(sentinel<!Const> s)
369
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
370
+
371
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
372
+ };
373
+ }
374
+ ```
375
+
376
+ ``` cpp
377
+ constexpr explicit sentinel(Parent& parent);
378
+ ```
379
+
380
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
381
+
382
+ ``` cpp
383
+ constexpr sentinel(sentinel<!Const> s)
384
+ requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
385
+ ```
386
+
387
+ *Effects:* Initializes *end\_* with `std::move(s.`*`end_`*`)`.
388
+
389
+ ``` cpp
390
+ friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
391
+ ```
392
+
393
+ *Effects:* Equivalent to: `return x.`*`outer_`*` == y.`*`end_`*`;`
394
+