From Jason Turner

[range.adjacent.transform]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmphts6vfs0/{from.md → to.md} +419 -0
tmp/tmphts6vfs0/{from.md → to.md} RENAMED
@@ -0,0 +1,419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Adjacent transform view <a id="range.adjacent.transform">[[range.adjacent.transform]]</a>
2
+
3
+ #### Overview <a id="range.adjacent.transform.overview">[[range.adjacent.transform.overview]]</a>
4
+
5
+ `adjacent_transform_view` takes an invocable object and a view and
6
+ produces a view whose Mᵗʰ element is the result of applying the
7
+ invocable object to the Mᵗʰ through (M + N - 1)ᵗʰ elements of the
8
+ original view. If the original view has fewer than N elements, the
9
+ resulting view is empty.
10
+
11
+ The name `views::adjacent_transform<N>` denotes a range adaptor object
12
+ [[range.adaptor.object]]. Given subexpressions `E` and `F` and a
13
+ constant expression `N`:
14
+
15
+ - If `N` is equal to `0`, `views::adjacent_transform<N>(E, F)` is
16
+ expression-equivalent to `((void)E, views::zip_transform(F))`, except
17
+ that the evaluations of `E` and `F` are indeterminately sequenced.
18
+ - Otherwise, the expression `views::adjacent_transform<N>(E, F)` is
19
+ expression-equivalent to
20
+ `adjacent_transform_view<views::all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F)`.
21
+
22
+ [*Example 1*:
23
+
24
+ ``` cpp
25
+ vector v = {1, 2, 3, 4};
26
+
27
+ for (auto i : v | views::adjacent_transform<2>(std::multiplies())) {
28
+ cout << i << ' '; // prints 2 6 12
29
+ }
30
+ ```
31
+
32
+ — *end example*]
33
+
34
+ #### Class template `adjacent_transform_view` <a id="range.adjacent.transform.view">[[range.adjacent.transform.view]]</a>
35
+
36
+ ``` cpp
37
+ namespace std::ranges {
38
+ template<forward_range V, move_constructible F, size_t N>
39
+ requires view<V> && (N > 0) && is_object_v<F> &&
40
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
41
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
42
+ class adjacent_transform_view : public view_interface<adjacent_transform_view<V, F, N>> {
43
+ movable-box<F> fun_; // exposition only
44
+ adjacent_view<V, N> inner_; // exposition only
45
+
46
+ using InnerView = adjacent_view<V, N>; // exposition only
47
+ template<bool Const>
48
+ using inner-iterator = iterator_t<maybe-const<Const, InnerView>>; // exposition only
49
+ template<bool Const>
50
+ using inner-sentinel = sentinel_t<maybe-const<Const, InnerView>>; // exposition only
51
+
52
+ // [range.adjacent.transform.iterator], class template adjacent_transform_view::iterator
53
+ template<bool> class iterator; // exposition only
54
+
55
+ // [range.adjacent.transform.sentinel], class template adjacent_transform_view::sentinel
56
+ template<bool> class sentinel; // exposition only
57
+
58
+ public:
59
+ adjacent_transform_view() = default;
60
+ constexpr explicit adjacent_transform_view(V base, F fun);
61
+
62
+ constexpr V base() const & requires copy_constructible<InnerView> { return inner_.base(); }
63
+ constexpr V base() && { return std::move(inner_).base(); }
64
+
65
+ constexpr auto begin() {
66
+ return iterator<false>(*this, inner_.begin());
67
+ }
68
+
69
+ constexpr auto begin() const
70
+ requires range<const InnerView> &&
71
+ regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> {
72
+ return iterator<true>(*this, inner_.begin());
73
+ }
74
+
75
+ constexpr auto end() {
76
+ if constexpr (common_range<InnerView>) {
77
+ return iterator<false>(*this, inner_.end());
78
+ } else {
79
+ return sentinel<false>(inner_.end());
80
+ }
81
+ }
82
+
83
+ constexpr auto end() const
84
+ requires range<const InnerView> &&
85
+ regular_invocable<const F&, REPEAT(range_reference_t<const V>, N)...> {
86
+ if constexpr (common_range<const InnerView>) {
87
+ return iterator<true>(*this, inner_.end());
88
+ } else {
89
+ return sentinel<true>(inner_.end());
90
+ }
91
+ }
92
+
93
+ constexpr auto size() requires sized_range<InnerView> {
94
+ return inner_.size();
95
+ }
96
+
97
+ constexpr auto size() const requires sized_range<const InnerView> {
98
+ return inner_.size();
99
+ }
100
+ };
101
+ }
102
+ ```
103
+
104
+ ``` cpp
105
+ constexpr explicit adjacent_transform_view(V base, F fun);
106
+ ```
107
+
108
+ *Effects:* Initializes *fun\_* with `std::move(fun)` and *inner\_* with
109
+ `std::move(base)`.
110
+
111
+ #### Class template `adjacent_transform_view::iterator` <a id="range.adjacent.transform.iterator">[[range.adjacent.transform.iterator]]</a>
112
+
113
+ ``` cpp
114
+ namespace std::ranges {
115
+ template<forward_range V, move_constructible F, size_t N>
116
+ requires view<V> && (N > 0) && is_object_v<F> &&
117
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
118
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
119
+ template<bool Const>
120
+ class adjacent_transform_view<V, F, N>::iterator {
121
+ using Parent = maybe-const<Const, adjacent_transform_view>; // exposition only
122
+ using Base = maybe-const<Const, V>; // exposition only
123
+ Parent* parent_ = nullptr; // exposition only
124
+ inner-iterator<Const> inner_; // exposition only
125
+
126
+ constexpr iterator(Parent& parent, inner-iterator<Const> inner); // exposition only
127
+
128
+ public:
129
+ using iterator_category = see below;
130
+ using iterator_concept = typename inner-iterator<Const>::iterator_concept;
131
+ using value_type =
132
+ remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
133
+ REPEAT(range_reference_t<Base>, N)...>>;
134
+ using difference_type = range_difference_t<Base>;
135
+
136
+ iterator() = default;
137
+ constexpr iterator(iterator<!Const> i)
138
+ requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
139
+
140
+ constexpr decltype(auto) operator*() const noexcept(see below);
141
+ constexpr iterator& operator++();
142
+ constexpr iterator operator++(int);
143
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
144
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
145
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
146
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
147
+
148
+ constexpr decltype(auto) operator[](difference_type n) const
149
+ requires random_access_range<Base>;
150
+
151
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
152
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
153
+ requires random_access_range<Base>;
154
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
155
+ requires random_access_range<Base>;
156
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
157
+ requires random_access_range<Base>;
158
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
159
+ requires random_access_range<Base>;
160
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
161
+ requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
162
+
163
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
164
+ requires random_access_range<Base>;
165
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
166
+ requires random_access_range<Base>;
167
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
168
+ requires random_access_range<Base>;
169
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
170
+ requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
171
+ };
172
+ }
173
+ ```
174
+
175
+ The member *typedef-name* `iterator::iterator_category` is defined as
176
+ follows:
177
+
178
+ - If `invoke_result_t<maybe-const<Const, F>&,
179
+ REPEAT(range_reference_t<Base>, N)...>` isnot a reference,
180
+ `iterator_category` denotes `input_iterator_tag`.
181
+ - Otherwise, let `C` denote the type
182
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
183
+ - If `derived_from<C, random_access_iterator_tag>` is `true`,
184
+ `iterator_category` denotes `random_access_iterator_tag`.
185
+ - Otherwise, if `derived_from<C, bidirectional_iterator_tag>` is
186
+ `true`, `iterator_category` denotes `bidirectional_iterator_tag`.
187
+ - Otherwise, if `derived_from<C, forward_iterator_tag>` is `true`,
188
+ `iterator_category` denotes `forward_iterator_tag`.
189
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
190
+
191
+ ``` cpp
192
+ constexpr iterator(Parent& parent, inner-iterator<Const> inner);
193
+ ```
194
+
195
+ *Effects:* Initializes *parent\_* with `addressof(parent)` and *inner\_*
196
+ with `std::move(inner)`.
197
+
198
+ ``` cpp
199
+ constexpr iterator(iterator<!Const> i)
200
+ requires Const && convertible_to<inner-iterator<false>, inner-iterator<Const>>;
201
+ ```
202
+
203
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *inner\_*
204
+ with `std::move(i.`*`inner_`*`)`.
205
+
206
+ ``` cpp
207
+ constexpr decltype(auto) operator*() const noexcept(see below);
208
+ ```
209
+
210
+ *Effects:* Equivalent to:
211
+
212
+ ``` cpp
213
+ return apply([&](const auto&... iters) -> decltype(auto) {
214
+ return invoke(*parent_->fun_, *iters...);
215
+ }, inner_.current_);
216
+ ```
217
+
218
+ *Remarks:* Let `Is` be the pack `0, 1, …, (N-1)`. The exception
219
+ specification is equivalent to:
220
+
221
+ ``` cpp
222
+ noexcept(invoke(*parent_->fun_, *std::get<Is>(inner_.current_)...))
223
+ ```
224
+
225
+ ``` cpp
226
+ constexpr iterator& operator++();
227
+ ```
228
+
229
+ *Effects:* Equivalent to:
230
+
231
+ ``` cpp
232
+ ++inner_;
233
+ return *this;
234
+ ```
235
+
236
+ ``` cpp
237
+ constexpr iterator operator++(int);
238
+ ```
239
+
240
+ *Effects:* Equivalent to:
241
+
242
+ ``` cpp
243
+ auto tmp = *this;
244
+ ++*this;
245
+ return tmp;
246
+ ```
247
+
248
+ ``` cpp
249
+ constexpr iterator& operator--() requires bidirectional_range<Base>;
250
+ ```
251
+
252
+ *Effects:* Equivalent to:
253
+
254
+ ``` cpp
255
+ --inner_;
256
+ return *this;
257
+ ```
258
+
259
+ ``` cpp
260
+ constexpr iterator operator--(int) requires bidirectional_range<Base>;
261
+ ```
262
+
263
+ *Effects:* Equivalent to:
264
+
265
+ ``` cpp
266
+ auto tmp = *this;
267
+ --*this;
268
+ return tmp;
269
+ ```
270
+
271
+ ``` cpp
272
+ constexpr iterator& operator+=(difference_type x) requires random_access_range<Base>;
273
+ ```
274
+
275
+ *Effects:* Equivalent to:
276
+
277
+ ``` cpp
278
+ inner_ += x;
279
+ return *this;
280
+ ```
281
+
282
+ ``` cpp
283
+ constexpr iterator& operator-=(difference_type x) requires random_access_range<Base>;
284
+ ```
285
+
286
+ *Effects:* Equivalent to:
287
+
288
+ ``` cpp
289
+ inner_ -= x;
290
+ return *this;
291
+ ```
292
+
293
+ ``` cpp
294
+ constexpr decltype(auto) operator[](difference_type n) const
295
+ requires random_access_range<Base>;
296
+ ```
297
+
298
+ *Effects:* Equivalent to:
299
+
300
+ ``` cpp
301
+ return apply([&](const auto&... iters) -> decltype(auto) {
302
+ return invoke(*parent_->fun_, iters[n]...);
303
+ }, inner_.current_);
304
+ ```
305
+
306
+ ``` cpp
307
+ friend constexpr bool operator==(const iterator& x, const iterator& y);
308
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
309
+ requires random_access_range<Base>;
310
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
311
+ requires random_access_range<Base>;
312
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
313
+ requires random_access_range<Base>;
314
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
315
+ requires random_access_range<Base>;
316
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
317
+ requires random_access_range<Base> && three_way_comparable<inner-iterator<Const>>;
318
+ ```
319
+
320
+ Let *op* be the operator.
321
+
322
+ *Effects:* Equivalent to:
323
+ `return x.`*`inner_`*` `*`op`*` y.`*`inner_`*`;`
324
+
325
+ ``` cpp
326
+ friend constexpr iterator operator+(const iterator& i, difference_type n)
327
+ requires random_access_range<Base>;
328
+ friend constexpr iterator operator+(difference_type n, const iterator& i)
329
+ requires random_access_range<Base>;
330
+ ```
331
+
332
+ *Effects:* Equivalent to:
333
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` + n);`
334
+
335
+ ``` cpp
336
+ friend constexpr iterator operator-(const iterator& i, difference_type n)
337
+ requires random_access_range<Base>;
338
+ ```
339
+
340
+ *Effects:* Equivalent to:
341
+ `return `*`iterator`*`(*i.`*`parent_`*`, i.`*`inner_`*` - n);`
342
+
343
+ ``` cpp
344
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
345
+ requires sized_sentinel_for<inner-iterator<Const>, inner-iterator<Const>>;
346
+ ```
347
+
348
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
349
+
350
+ #### Class template `adjacent_transform_view::sentinel` <a id="range.adjacent.transform.sentinel">[[range.adjacent.transform.sentinel]]</a>
351
+
352
+ ``` cpp
353
+ namespace std::ranges {
354
+ template<forward_range V, move_constructible F, size_t N>
355
+ requires view<V> && (N > 0) && is_object_v<F> &&
356
+ regular_invocable<F&, REPEAT(range_reference_t<V>, N)...> &&
357
+ can-reference<invoke_result_t<F&, REPEAT(range_reference_t<V>, N)...>>
358
+ template<bool Const>
359
+ class adjacent_transform_view<V, F, N>::sentinel {
360
+ inner-sentinel<Const> inner_; // exposition only
361
+ constexpr explicit sentinel(inner-sentinel<Const> inner); // exposition only
362
+
363
+ public:
364
+ sentinel() = default;
365
+ constexpr sentinel(sentinel<!Const> i)
366
+ requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
367
+
368
+ template<bool OtherConst>
369
+ requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
370
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
371
+
372
+ template<bool OtherConst>
373
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
374
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
375
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
376
+
377
+ template<bool OtherConst>
378
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
379
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
380
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
381
+ };
382
+ }
383
+ ```
384
+
385
+ ``` cpp
386
+ constexpr explicit sentinel(inner-sentinel<Const> inner);
387
+ ```
388
+
389
+ *Effects:* Initializes *inner\_* with `inner`.
390
+
391
+ ``` cpp
392
+ constexpr sentinel(sentinel<!Const> i)
393
+ requires Const && convertible_to<inner-sentinel<false>, inner-sentinel<Const>>;
394
+ ```
395
+
396
+ *Effects:* Initializes *inner\_* with `std::move(i.`*`inner_`*`)`.
397
+
398
+ ``` cpp
399
+ template<bool OtherConst>
400
+ requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
401
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
402
+ ```
403
+
404
+ *Effects:* Equivalent to `return x.`*`inner_`*` == y.`*`inner_`*`;`
405
+
406
+ ``` cpp
407
+ template<bool OtherConst>
408
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
409
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
410
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
411
+
412
+ template<bool OtherConst>
413
+ requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
414
+ friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
415
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
416
+ ```
417
+
418
+ *Effects:* Equivalent to `return x.`*`inner_`*` - y.`*`inner_`*`;`
419
+