From Jason Turner

[range.join.iterator]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpu6wuyn9k/{from.md → to.md} +88 -60
tmp/tmpu6wuyn9k/{from.md → to.md} RENAMED
@@ -1,47 +1,53 @@
1
  #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
2
 
3
  ``` cpp
4
  namespace std::ranges {
5
  template<input_range V>
6
- requires view<V> && input_range<range_reference_t<V>> &&
7
- (is_reference_v<range_reference_t<V>> ||
8
- view<range_value_t<V>>)
9
  template<bool Const>
10
  struct join_view<V>::iterator {
11
  private:
12
- using Parent = // exposition only
13
- conditional_t<Const, const join_view, join_view>;
14
- using Base = conditional_t<Const, const V, V>; // exposition only
 
15
 
16
  static constexpr bool ref-is-glvalue = // exposition only
17
  is_reference_v<range_reference_t<Base>>;
18
 
19
- iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only
20
- iterator_t<range_reference_t<Base>> inner_ = // exposition only
21
- iterator_t<range_reference_t<Base>>();
22
  Parent* parent_ = nullptr; // exposition only
23
 
24
  constexpr void satisfy(); // exposition only
 
 
 
 
 
 
 
 
 
25
  public:
26
  using iterator_concept = see below;
27
- using iterator_category = see below;
28
  using value_type = range_value_t<range_reference_t<Base>>;
29
  using difference_type = see below;
30
 
31
  iterator() = default;
32
- constexpr iterator(Parent& parent, iterator_t<Base> outer);
33
  constexpr iterator(iterator<!Const> i)
34
  requires Const &&
35
- convertible_to<iterator_t<V>, iterator_t<Base>> &&
36
- convertible_to<iterator_t<InnerRng>,
37
- iterator_t<range_reference_t<Base>>>;
38
 
39
- constexpr decltype(auto) operator*() const { return *inner_; }
40
 
41
- constexpr iterator_t<Base> operator->() const
42
- requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
43
 
44
  constexpr iterator& operator++();
45
  constexpr void operator++(int);
46
  constexpr iterator operator++(int)
47
  requires ref-is-glvalue && forward_range<Base> &&
@@ -56,50 +62,53 @@ namespace std::ranges {
56
  requires ref-is-glvalue && bidirectional_range<Base> &&
57
  bidirectional_range<range_reference_t<Base>> &&
58
  common_range<range_reference_t<Base>>;
59
 
60
  friend constexpr bool operator==(const iterator& x, const iterator& y)
61
- requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
62
  equality_comparable<iterator_t<range_reference_t<Base>>>;
63
 
64
  friend constexpr decltype(auto) iter_move(const iterator& i)
65
- noexcept(noexcept(ranges::iter_move(i.inner_))) {
66
- return ranges::iter_move(i.inner_);
67
  }
68
 
69
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
70
- noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
 
71
  };
72
  }
73
  ```
74
 
75
  `iterator::iterator_concept` is defined as follows:
76
 
77
- - If *`ref-is-glvalue`* is `true` and *`Base`* and
78
- `range_reference_t<Base>` each model `bidirectional_range`, then
79
- `iterator_concept` denotes `bidirectional_iterator_tag`.
 
80
  - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
81
  `range_reference_t<Base>` each model , then `iterator_concept` denotes
82
  `forward_iterator_tag`.
83
  - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
84
 
 
 
 
85
  `iterator::iterator_category` is defined as follows:
86
 
87
  - Let *OUTERC* denote
88
  `iterator_traits<iterator_t<Base>>::iterator_category`, and let
89
  *INNERC* denote
90
  `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
91
- - If *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC* each model
92
- `derived_from<bidirectional_iterator_tag>`, `iterator_category`
 
93
  denotes `bidirectional_iterator_tag`.
94
- - Otherwise, if *`ref-is-glvalue`* is `true` and *OUTERC* and *INNERC*
95
- each model `derived_from<forward_iterator_tag>`, `iterator_category`
96
- denotes `forward_iterator_tag`.
97
  - Otherwise, if *OUTERC* and *INNERC* each model
98
- `derived_from<input_iterator_tag>`, `iterator_category` denotes
99
- `input_iterator_tag`.
100
- - Otherwise, `iterator_category` denotes `output_iterator_tag`.
101
 
102
  `iterator::difference_type` denotes the type:
103
 
104
  ``` cpp
105
  common_type_t<
@@ -109,74 +118,92 @@ common_type_t<
109
 
110
  `join_view` iterators use the *`satisfy`* function to skip over empty
111
  inner ranges.
112
 
113
  ``` cpp
114
- constexpr void satisfy(); // exposition only
 
 
 
 
 
 
 
 
115
  ```
116
 
117
  *Effects:* Equivalent to:
118
 
119
  ``` cpp
120
- auto update_inner = [this](range_reference_t<Base> x) -> auto& {
121
- if constexpr (ref-is-glvalue) // x is a reference
122
- return x;
123
  else
124
- return (parent_->inner_ = views::all(std::move(x)));
125
  };
126
 
127
- for (; outer_ != ranges::end(parent_->base_); ++outer_) {
128
- auto& inner = update_inner(*outer_);
129
  inner_ = ranges::begin(inner);
130
- if (inner_ != ranges::end(inner))
131
  return;
132
  }
133
  if constexpr (ref-is-glvalue)
134
- inner_ = iterator_t<range_reference_t<Base>>();
135
  ```
136
 
137
  ``` cpp
138
- constexpr iterator(Parent& parent, iterator_t<Base> outer);
 
139
  ```
140
 
141
  *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
142
  with `addressof(parent)`; then calls *`satisfy`*`()`.
143
 
 
 
 
 
 
 
 
 
144
  ``` cpp
145
  constexpr iterator(iterator<!Const> i)
146
  requires Const &&
147
- convertible_to<iterator_t<V>, iterator_t<Base>> &&
148
- convertible_to<iterator_t<InnerRng>,
149
- iterator_t<range_reference_t<Base>>>;
150
  ```
151
 
152
  *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
153
  *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
154
  `i.`*`parent_`*.
155
 
 
 
 
156
  ``` cpp
157
- constexpr iterator_t<Base> operator->() const
158
- requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;
159
  ```
160
 
161
- *Effects:* Equivalent to `return `*`inner_`*`;`
162
 
163
  ``` cpp
164
  constexpr iterator& operator++();
165
  ```
166
 
167
  Let *`inner-range`* be:
168
 
169
- - If *ref-is-glvalue* is `true`, `*`*`outer_`*.
170
- - Otherwise, *`parent_`*`->`*`inner_`*.
171
 
172
  *Effects:* Equivalent to:
173
 
174
  ``` cpp
175
- auto&& inner_rng = inner-range;
176
- if (++inner_ == ranges::end(inner_rng)) {
177
- ++outer_;
178
  satisfy();
179
  }
180
  return *this;
181
  ```
182
 
@@ -209,14 +236,14 @@ constexpr iterator& operator--()
209
 
210
  *Effects:* Equivalent to:
211
 
212
  ``` cpp
213
  if (outer_ == ranges::end(parent_->base_))
214
- inner_ = ranges::end(*--outer_);
215
- while (inner_ == ranges::begin(*outer_))
216
- inner_ = ranges::end(*--outer_);
217
- --inner_;
218
  return *this;
219
  ```
220
 
221
  ``` cpp
222
  constexpr iterator operator--(int)
@@ -233,20 +260,21 @@ auto tmp = *this;
233
  return tmp;
234
  ```
235
 
236
  ``` cpp
237
  friend constexpr bool operator==(const iterator& x, const iterator& y)
238
- requires ref-is-glvalue && equality_comparable<iterator_t<Base>> &&
239
  equality_comparable<iterator_t<range_reference_t<Base>>>;
240
  ```
241
 
242
  *Effects:* Equivalent to:
243
  `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
244
 
245
  ``` cpp
246
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
247
- noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));
 
248
  ```
249
 
250
  *Effects:* Equivalent to:
251
- `return ranges::iter_swap(x.`*`inner_`*`, y.`*`inner_`*`);`
252
 
 
1
  #### Class template `join_view::iterator` <a id="range.join.iterator">[[range.join.iterator]]</a>
2
 
3
  ``` cpp
4
  namespace std::ranges {
5
  template<input_range V>
6
+ requires view<V> && input_range<range_reference_t<V>>
 
 
7
  template<bool Const>
8
  struct join_view<V>::iterator {
9
  private:
10
+ using Parent = maybe-const<Const, join_view>; // exposition only
11
+ using Base = maybe-const<Const, V>; // exposition only
12
+ using OuterIter = iterator_t<Base>; // exposition only
13
+ using InnerIter = iterator_t<range_reference_t<Base>>; // exposition only
14
 
15
  static constexpr bool ref-is-glvalue = // exposition only
16
  is_reference_v<range_reference_t<Base>>;
17
 
18
+ OuterIter outer_ = OuterIter(); // exposition only, present only
19
+ // if Base models forward_range
20
+ optional<InnerIter> inner_; // exposition only
21
  Parent* parent_ = nullptr; // exposition only
22
 
23
  constexpr void satisfy(); // exposition only
24
+
25
+ constexpr OuterIter& outer(); // exposition only
26
+ constexpr const OuterIter& outer() const; // exposition only
27
+
28
+ constexpr iterator(Parent& parent, OuterIter outer)
29
+ requires forward_range<Base>; // exposition only
30
+ constexpr explicit iterator(Parent& parent)
31
+ requires (!forward_range<Base>); // exposition only
32
+
33
  public:
34
  using iterator_concept = see below;
35
+ using iterator_category = see below; // not always present
36
  using value_type = range_value_t<range_reference_t<Base>>;
37
  using difference_type = see below;
38
 
39
  iterator() = default;
 
40
  constexpr iterator(iterator<!Const> i)
41
  requires Const &&
42
+ convertible_to<iterator_t<V>, OuterIter> &&
43
+ convertible_to<iterator_t<InnerRng>, InnerIter>;
 
44
 
45
+ constexpr decltype(auto) operator*() const { return **inner_; }
46
 
47
+ constexpr InnerIter operator->() const
48
+ requires has-arrow<InnerIter> && copyable<InnerIter>;
49
 
50
  constexpr iterator& operator++();
51
  constexpr void operator++(int);
52
  constexpr iterator operator++(int)
53
  requires ref-is-glvalue && forward_range<Base> &&
 
62
  requires ref-is-glvalue && bidirectional_range<Base> &&
63
  bidirectional_range<range_reference_t<Base>> &&
64
  common_range<range_reference_t<Base>>;
65
 
66
  friend constexpr bool operator==(const iterator& x, const iterator& y)
67
+ requires ref-is-glvalue && forward_range<Base> &&
68
  equality_comparable<iterator_t<range_reference_t<Base>>>;
69
 
70
  friend constexpr decltype(auto) iter_move(const iterator& i)
71
+ noexcept(noexcept(ranges::iter_move(*i.inner_))) {
72
+ return ranges::iter_move(*i.inner_);
73
  }
74
 
75
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
76
+ noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
77
+ requires indirectly_swappable<InnerIter>;
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 `range_reference_t<Base>` models both
86
+ `bidirectional_range` and `common_range`, then `iterator_concept`
87
+ denotes `bidirectional_iterator_tag`.
88
  - Otherwise, if *`ref-is-glvalue`* is `true` and *`Base`* and
89
  `range_reference_t<Base>` each model , then `iterator_concept` denotes
90
  `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`, *`Base`* models `forward_range`, and
95
+ `range_reference_t<Base>` models `forward_range`. In that case,
96
  `iterator::iterator_category` is defined as follows:
97
 
98
  - Let *OUTERC* denote
99
  `iterator_traits<iterator_t<Base>>::iterator_category`, and let
100
  *INNERC* denote
101
  `iterator_traits<iterator_t<range_reference_t<Base>>>::iterator_category`.
102
+ - If *OUTERC* and *INNERC* each model
103
+ `derived_from<bidirectional_iterator_tag>` and
104
+ `range_reference_t<Base>` models `common_range`, `iterator_category`
105
  denotes `bidirectional_iterator_tag`.
 
 
 
106
  - Otherwise, if *OUTERC* and *INNERC* each model
107
+ `derived_from<forward_iterator_tag>`, `iterator_category` denotes
108
+ `forward_iterator_tag`.
109
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
110
 
111
  `iterator::difference_type` denotes the type:
112
 
113
  ``` cpp
114
  common_type_t<
 
118
 
119
  `join_view` iterators use the *`satisfy`* function to skip over empty
120
  inner ranges.
121
 
122
  ``` cpp
123
+ constexpr OuterIter& outer();
124
+ constexpr const OuterIter& outer() const;
125
+ ```
126
+
127
+ *Returns:* *outer\_* if *Base* models `forward_range`; otherwise,
128
+ `*`*`parent_`*`->`*`outer_`*.
129
+
130
+ ``` cpp
131
+ constexpr void satisfy();
132
  ```
133
 
134
  *Effects:* Equivalent to:
135
 
136
  ``` cpp
137
+ auto update_inner = [this](const iterator_t<Base>& x) -> auto&& {
138
+ if constexpr (ref-is-glvalue) // *x is a reference
139
+ return *x;
140
  else
141
+ return parent_->inner_.emplace-deref(x);
142
  };
143
 
144
+ for (; outer() != ranges::end(parent_->base_); ++outer()) {
145
+ auto&& inner = update_inner(outer());
146
  inner_ = ranges::begin(inner);
147
+ if (*inner_ != ranges::end(inner))
148
  return;
149
  }
150
  if constexpr (ref-is-glvalue)
151
+ inner_.reset();
152
  ```
153
 
154
  ``` cpp
155
+ constexpr iterator(Parent& parent, OuterIter outer)
156
+ requires forward_range<Base>;
157
  ```
158
 
159
  *Effects:* Initializes *outer\_* with `std::move(outer)` and *parent\_*
160
  with `addressof(parent)`; then calls *`satisfy`*`()`.
161
 
162
+ ``` cpp
163
+ constexpr explicit iterator(Parent& parent)
164
+ requires (!forward_range<Base>);
165
+ ```
166
+
167
+ *Effects:* Initializes *parent\_* with `addressof(parent)`; then calls
168
+ *`satisfy`*`()`.
169
+
170
  ``` cpp
171
  constexpr iterator(iterator<!Const> i)
172
  requires Const &&
173
+ convertible_to<iterator_t<V>, OuterIter> &&
174
+ convertible_to<iterator_t<InnerRng>, InnerIter>;
 
175
  ```
176
 
177
  *Effects:* Initializes *outer\_* with `std::move(i.`*`outer_`*`)`,
178
  *inner\_* with `std::move(i.`*`inner_`*`)`, and *parent\_* with
179
  `i.`*`parent_`*.
180
 
181
+ [*Note 1*: `Const` can only be `true` when *Base* models
182
+ `forward_range`. — *end note*]
183
+
184
  ``` cpp
185
+ constexpr InnerIter operator->() const
186
+ requires has-arrow<InnerIter> && copyable<InnerIter>;
187
  ```
188
 
189
+ *Effects:* Equivalent to: `return *`*`inner_`*`;`
190
 
191
  ``` cpp
192
  constexpr iterator& operator++();
193
  ```
194
 
195
  Let *`inner-range`* be:
196
 
197
+ - If *ref-is-glvalue* is `true`, `*`*`outer`*`()`.
198
+ - Otherwise, `*`*`parent_`*`->`*`inner_`*.
199
 
200
  *Effects:* Equivalent to:
201
 
202
  ``` cpp
203
+ if (++*inner_ == ranges::end(as-lvalue(inner-range))) {
204
+ ++outer();
 
205
  satisfy();
206
  }
207
  return *this;
208
  ```
209
 
 
236
 
237
  *Effects:* Equivalent to:
238
 
239
  ``` cpp
240
  if (outer_ == ranges::end(parent_->base_))
241
+ inner_ = ranges::end(as-lvalue(*--outer_));
242
+ while (*inner_ == ranges::begin(as-lvalue(*outer_)))
243
+ *inner_ = ranges::end(as-lvalue(*--outer_));
244
+ --*inner_;
245
  return *this;
246
  ```
247
 
248
  ``` cpp
249
  constexpr iterator operator--(int)
 
260
  return tmp;
261
  ```
262
 
263
  ``` cpp
264
  friend constexpr bool operator==(const iterator& x, const iterator& y)
265
+ requires ref-is-glvalue && forward_range<Base> &&
266
  equality_comparable<iterator_t<range_reference_t<Base>>>;
267
  ```
268
 
269
  *Effects:* Equivalent to:
270
  `return x.`*`outer_`*` == y.`*`outer_`*` && x.`*`inner_`*` == y.`*`inner_`*`;`
271
 
272
  ``` cpp
273
  friend constexpr void iter_swap(const iterator& x, const iterator& y)
274
+ noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
275
+ requires indirectly_swappable<InnerIter>;
276
  ```
277
 
278
  *Effects:* Equivalent to:
279
+ `return ranges::iter_swap(*x.`*`inner_`*`, *y.`*`inner_`*`);`
280