From Jason Turner

[range.join.with.iterator]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpdf06dx2_/{from.md → to.md} +338 -0
tmp/tmpdf06dx2_/{from.md → to.md} RENAMED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Class template `join_with_view::iterator` <a id="range.join.with.iterator">[[range.join.with.iterator]]</a>
2
+
3
+ ``` cpp
4
+ namespace std::ranges {
5
+ template<input_range V, forward_range Pattern>
6
+ requires view<V> && input_range<range_reference_t<V>>
7
+ && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
8
+ template<bool Const>
9
+ class join_with_view<V, Pattern>::iterator {
10
+ using Parent = maybe-const<Const, join_with_view>; // exposition only
11
+ using Base = maybe-const<Const, V>; // exposition only
12
+ using InnerBase = range_reference_t<Base>; // exposition only
13
+ using PatternBase = maybe-const<Const, Pattern>; // exposition only
14
+
15
+ using OuterIter = iterator_t<Base>; // exposition only
16
+ using InnerIter = iterator_t<InnerBase>; // exposition only
17
+ using PatternIter = iterator_t<PatternBase>; // exposition only
18
+
19
+ static constexpr bool ref-is-glvalue = is_reference_v<InnerBase>; // exposition only
20
+
21
+ Parent* parent_ = nullptr; // exposition only
22
+ OuterIter outer_it_ = OuterIter(); // exposition only, present only
23
+ // if Base models forward_range
24
+ variant<PatternIter, InnerIter> inner_it_; // exposition only
25
+
26
+ constexpr iterator(Parent& parent, OuterIter outer)
27
+ requires forward_range<Base>; // exposition only
28
+ constexpr explicit iterator(Parent& parent)
29
+ requires (!forward_range<Base>); // exposition only
30
+ constexpr OuterIter& outer(); // exposition only
31
+ constexpr const OuterIter& outer() const; // exposition only
32
+ constexpr auto& update-inner(); // exposition only
33
+ constexpr auto& get-inner(); // exposition only
34
+ constexpr void satisfy(); // exposition only
35
+
36
+ public:
37
+ using iterator_concept = see below;
38
+ using iterator_category = see below; // not always present
39
+ using value_type = see below;
40
+ using difference_type = see below;
41
+
42
+ iterator() = default;
43
+ constexpr iterator(iterator<!Const> i)
44
+ requires Const && convertible_to<iterator_t<V>, OuterIter> &&
45
+ convertible_to<iterator_t<InnerRng>, InnerIter> &&
46
+ convertible_to<iterator_t<Pattern>, PatternIter>;
47
+
48
+ constexpr decltype(auto) operator*() const;
49
+
50
+ constexpr iterator& operator++();
51
+ constexpr void operator++(int);
52
+ constexpr iterator operator++(int)
53
+ requires ref-is-glvalue && forward_iterator<OuterIter> &&
54
+ forward_iterator<InnerIter>;
55
+
56
+ constexpr iterator& operator--()
57
+ requires ref-is-glvalue && bidirectional_range<Base> &&
58
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
59
+ constexpr iterator operator--(int)
60
+ requires ref-is-glvalue && bidirectional_range<Base> &&
61
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
62
+
63
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
64
+ requires ref-is-glvalue && forward_range<Base> &&
65
+ equality_comparable<InnerIter>;
66
+
67
+ friend constexpr decltype(auto) iter_move(const iterator& x) {
68
+ using rvalue_reference = common_reference_t<
69
+ iter_rvalue_reference_t<InnerIter>,
70
+ iter_rvalue_reference_t<PatternIter>>;
71
+ return visit<rvalue_reference>(ranges::iter_move, x.inner_it_);
72
+ }
73
+
74
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
75
+ requires indirectly_swappable<InnerIter, PatternIter> {
76
+ visit(ranges::iter_swap, x.inner_it_, y.inner_it_);
77
+ }
78
+ };
79
+ }
80
+ ```
81
+
82
+ `iterator::iterator_concept` is defined as follows:
83
+
84
+ - If *`ref-is-glvalue`* is `true`, *`Base`* models
85
+ `bidirectional_range`, and *`InnerBase`* and *`PatternBase`* each
86
+ model `bidirectional-common`, then `iterator_concept` denotes
87
+ `bidirectional_iterator_tag`.
88
+ - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
89
+ *`InnerBase`* each model `forward_range`, then `iterator_concept`
90
+ denotes `forward_iterator_tag`.
91
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
92
+
93
+ The member *typedef-name* `iterator_category` is defined if and only if
94
+ *`ref-is-glvalue`* is `true`, and *`Base`* and *`InnerBase`* each model
95
+ `forward_range`. In that case, `iterator::iterator_category` is defined
96
+ as follows:
97
+
98
+ - Let *OUTERC* denote `iterator_traits<OuterIter>::iterator_category`,
99
+ let *INNERC* denote `iterator_traits<InnerIter>::iterator_category`,
100
+ and let *PATTERNC* denote
101
+ `iterator_-traits<PatternIter>::iterator_category`.
102
+ - If
103
+ ``` cpp
104
+ is_reference_v<common_reference_t<iter_reference_t<InnerIter>,
105
+ iter_reference_t<PatternIter>>>
106
+ ```
107
+
108
+ is `false`, `iterator_category` denotes `input_iterator_tag`.
109
+ - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
110
+ `derived_from<bidirectional_iterator_category>` and *`InnerBase`* and
111
+ *`PatternBase`* each model `common_range`, `iterator_category` denotes
112
+ `bidirectional_iterator_tag`.
113
+ - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
114
+ `derived_from<forward_iterator_tag>`, `iterator_category` denotes
115
+ `forward_iterator_tag`.
116
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
117
+
118
+ `iterator::value_type` denotes the type:
119
+
120
+ ``` cpp
121
+ common_type_t<iter_value_t<InnerIter>, iter_value_t<PatternIter>>
122
+ ```
123
+
124
+ `iterator::difference_type` denotes the type:
125
+
126
+ ``` cpp
127
+ common_type_t<
128
+ iter_difference_t<OuterIter>,
129
+ iter_difference_t<InnerIter>,
130
+ iter_difference_t<PatternIter>>
131
+ ```
132
+
133
+ ``` cpp
134
+ constexpr OuterIter& outer();
135
+ constexpr const OuterIter& outer() const;
136
+ ```
137
+
138
+ *Returns:* *outer_it\_* if *Base* models `forward_range`; otherwise,
139
+ `*`*`parent_`*`->`*`outer_it_`*.
140
+
141
+ ``` cpp
142
+ constexpr auto& update-inner();
143
+ ```
144
+
145
+ *Effects:* Equivalent to:
146
+
147
+ ``` cpp
148
+ if constexpr (ref-is-glvalue)
149
+ return as-lvalue(*outer());
150
+ else
151
+ return parent_->inner_.emplace-deref(outer());
152
+ ```
153
+
154
+ ``` cpp
155
+ constexpr auto& get-inner();
156
+ ```
157
+
158
+ *Effects:* Equivalent to:
159
+
160
+ ``` cpp
161
+ if constexpr (ref-is-glvalue)
162
+ return as-lvalue(*outer());
163
+ else
164
+ return *parent_->inner_;
165
+ ```
166
+
167
+ ``` cpp
168
+ constexpr void satisfy();
169
+ ```
170
+
171
+ *Effects:* Equivalent to:
172
+
173
+ ``` cpp
174
+ while (true) {
175
+ if (inner_it_.index() == 0) {
176
+ if (std::get<0>(inner_it_) != ranges::end(parent_->pattern_))
177
+ break;
178
+ inner_it_.emplace<1>(ranges::begin(update-inner()));
179
+ } else {
180
+ if (std::get<1>(inner_it_) != ranges::end(get-inner()))
181
+ break;
182
+ if (++outer() == ranges::end(parent_->base_)) {
183
+ if constexpr (ref-is-glvalue)
184
+ inner_it_.emplace<0>();
185
+ break;
186
+ }
187
+ inner_it_.emplace<0>(ranges::begin(parent_->pattern_));
188
+ }
189
+ }
190
+ ```
191
+
192
+ [*Note 1*: `join_with_view` iterators use the *satisfy* function to
193
+ skip over empty inner ranges. — *end note*]
194
+
195
+ ``` cpp
196
+ constexpr iterator(Parent& parent, OuterIter outer)
197
+ requires forward_range<Base>;
198
+ constexpr explicit iterator(Parent& parent)
199
+ requires (!forward_range<Base>);
200
+ ```
201
+
202
+ *Effects:* Initializes *parent\_* with `addressof(parent)`. For the
203
+ first overload, also initializes *outer_it\_* with `std::move(outer)`.
204
+ Then, equivalent to:
205
+
206
+ ``` cpp
207
+ if (outer() != ranges::end(parent_->base_)) {
208
+ inner_it_.emplace<1>(ranges::begin(update-inner()));
209
+ satisfy();
210
+ }
211
+ ```
212
+
213
+ ``` cpp
214
+ constexpr iterator(iterator<!Const> i)
215
+ requires Const && convertible_to<iterator_t<V>, OuterIter> &&
216
+ convertible_to<iterator_t<InnerRng>, InnerIter> &&
217
+ convertible_to<iterator_t<Pattern>, PatternIter>;
218
+ ```
219
+
220
+ *Effects:* Initializes *outer_it\_* with `std::move(i.`*`outer_it_`*`)`
221
+ and *parent\_* with `i.`*`parent_`*. Then, equivalent to:
222
+
223
+ ``` cpp
224
+ if (i.inner_it_.index() == 0)
225
+ inner_it_.emplace<0>(std::get<0>(std::move(i.inner_it_)));
226
+ else
227
+ inner_it_.emplace<1>(std::get<1>(std::move(i.inner_it_)));
228
+ ```
229
+
230
+ [*Note 2*: `Const` can only be `true` when *Base* models
231
+ `forward_range`. — *end note*]
232
+
233
+ ``` cpp
234
+ constexpr decltype(auto) operator*() const;
235
+ ```
236
+
237
+ *Effects:* Equivalent to:
238
+
239
+ ``` cpp
240
+ using reference =
241
+ common_reference_t<iter_reference_t<InnerIter>, iter_reference_t<PatternIter>>;
242
+ return visit([](auto& it) -> reference { return *it; }, inner_it_);
243
+ ```
244
+
245
+ ``` cpp
246
+ constexpr iterator& operator++();
247
+ ```
248
+
249
+ *Effects:* Equivalent to:
250
+
251
+ ``` cpp
252
+ visit([](auto& it){ ++it; }, inner_it_);
253
+ satisfy();
254
+ return *this;
255
+ ```
256
+
257
+ ``` cpp
258
+ constexpr void operator++(int);
259
+ ```
260
+
261
+ *Effects:* Equivalent to `++*this`.
262
+
263
+ ``` cpp
264
+ constexpr iterator operator++(int)
265
+ requires ref-is-glvalue && forward_iterator<OuterIter> && forward_iterator<InnerIter>;
266
+ ```
267
+
268
+ *Effects:* Equivalent to:
269
+
270
+ ``` cpp
271
+ iterator tmp = *this;
272
+ ++*this;
273
+ return tmp;
274
+ ```
275
+
276
+ ``` cpp
277
+ constexpr iterator& operator--()
278
+ requires ref-is-glvalue && bidirectional_range<Base> &&
279
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
280
+ ```
281
+
282
+ *Effects:* Equivalent to:
283
+
284
+ ``` cpp
285
+ if (outer_it_ == ranges::end(parent_->base_)) {
286
+ auto&& inner = *--outer_it_;
287
+ inner_it_.emplace<1>(ranges::end(inner));
288
+ }
289
+
290
+ while (true) {
291
+ if (inner_it_.index() == 0) {
292
+ auto& it = std::get<0>(inner_it_);
293
+ if (it == ranges::begin(parent_->pattern_)) {
294
+ auto&& inner = *--outer_it_;
295
+ inner_it_.emplace<1>(ranges::end(inner));
296
+ } else {
297
+ break;
298
+ }
299
+ } else {
300
+ auto& it = std::get<1>(inner_it_);
301
+ auto&& inner = *outer_it_;
302
+ if (it == ranges::begin(inner)) {
303
+ inner_it_.emplace<0>(ranges::end(parent_->pattern_));
304
+ } else {
305
+ break;
306
+ }
307
+ }
308
+ }
309
+ visit([](auto& it){ --it; }, inner_it_);
310
+ return *this;
311
+ ```
312
+
313
+ ``` cpp
314
+ constexpr iterator operator--(int)
315
+ requires ref-is-glvalue && bidirectional_range<Base> &&
316
+ bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;
317
+ ```
318
+
319
+ *Effects:* Equivalent to:
320
+
321
+ ``` cpp
322
+ iterator tmp = *this;
323
+ --*this;
324
+ return tmp;
325
+ ```
326
+
327
+ ``` cpp
328
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
329
+ requires ref-is-glvalue && forward_range<Base> &&
330
+ equality_comparable<InnerIter>;
331
+ ```
332
+
333
+ *Effects:* Equivalent to:
334
+
335
+ ``` cpp
336
+ return x.outer_it_ == y.outer_it_ && x.inner_it_ == y.inner_it_;
337
+ ```
338
+