From Jason Turner

[range.zip.transform]

Diff to HTML by rtfpessoa

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