From Jason Turner

[range.elements]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpzwjxl8z3/{from.md → to.md} +112 -180
tmp/tmpzwjxl8z3/{from.md → to.md} RENAMED
@@ -1,12 +1,12 @@
1
  ### Elements view <a id="range.elements">[[range.elements]]</a>
2
 
3
  #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
4
 
5
- `elements_view` takes a `view` of tuple-like values and a `size_t`, and
6
- produces a `view` with a value-type of the Nᵗʰ element of the adapted
7
- `view`’s value-type.
8
 
9
  The name `views::elements<N>` denotes a range adaptor object
10
  [[range.adaptor.object]]. Given a subexpression `E` and constant
11
  expression `N`, the expression `views::elements<N>(E)` is
12
  expression-equivalent to
@@ -14,11 +14,11 @@ expression-equivalent to
14
 
15
  [*Example 1*:
16
 
17
  ``` cpp
18
  auto historical_figures = map{
19
- {"Lovelace"sv, 1815},
20
  {"Turing"sv, 1912},
21
  {"Babbage"sv, 1791},
22
  {"Hamilton"sv, 1936}
23
  };
24
 
@@ -33,71 +33,70 @@ for (auto&& born : birth_years) {
33
  }
34
  ```
35
 
36
  — *end example*]
37
 
38
- `keys_view` is an alias for `elements_view<views::all_t<R>, 0>`, and is
39
- useful for extracting keys from associative containers.
40
 
41
  [*Example 2*:
42
 
43
  ``` cpp
44
- auto names = keys_view{historical_figures};
45
  for (auto&& name : names) {
46
  cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
47
  }
48
  ```
49
 
50
  — *end example*]
51
 
52
- `values_view` is an alias for `elements_view<views::all_t<R>, 1>`, and
53
- is useful for extracting values from associative containers.
54
 
55
  [*Example 3*:
56
 
57
  ``` cpp
58
  auto is_even = [](const auto x) { return x % 2 == 0; };
59
- cout << ranges::count_if(values_view{historical_figures}, is_even); // prints 2
60
  ```
61
 
62
  — *end example*]
63
 
64
  #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
65
 
66
  ``` cpp
67
  namespace std::ranges {
68
  template<class T, size_t N>
69
  concept has-tuple-element = // exposition only
70
- requires(T t) {
71
- typename tuple_size<T>::type;
72
- requires N < tuple_size_v<T>;
73
- typename tuple_element_t<N, T>;
74
- { get<N>(t) } -> convertible_to<const tuple_element_t<N, T>&>;
75
- };
76
 
 
 
 
77
 
78
  template<input_range V, size_t N>
79
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
80
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
81
  class elements_view : public view_interface<elements_view<V, N>> {
82
  public:
83
- elements_view() = default;
84
  constexpr explicit elements_view(V base);
85
 
86
  constexpr V base() const & requires copy_constructible<V> { return base_; }
87
  constexpr V base() && { return std::move(base_); }
88
 
89
  constexpr auto begin() requires (!simple-view<V>)
90
  { return iterator<false>(ranges::begin(base_)); }
91
 
92
- constexpr auto begin() const requires simple-view<V>
93
  { return iterator<true>(ranges::begin(base_)); }
94
 
95
- constexpr auto end()
96
  { return sentinel<false>{ranges::end(base_)}; }
97
 
98
- constexpr auto end() requires common_range<V>
99
  { return iterator<false>{ranges::end(base_)}; }
100
 
101
  constexpr auto end() const requires range<const V>
102
  { return sentinel<true>{ranges::end(base_)}; }
103
 
@@ -110,13 +109,15 @@ namespace std::ranges {
110
  constexpr auto size() const requires sized_range<const V>
111
  { return ranges::size(base_); }
112
 
113
  private:
114
  // [range.elements.iterator], class template elements_view::iterator
115
- template<bool> struct iterator; // exposition only
 
116
  // [range.elements.sentinel], class template elements_view::sentinel
117
- template<bool> struct sentinel; // exposition only
 
118
  V base_ = V(); // exposition only
119
  };
120
  }
121
  ```
122
 
@@ -130,35 +131,39 @@ constexpr explicit elements_view(V base);
130
 
131
  ``` cpp
132
  namespace std::ranges {
133
  template<input_range V, size_t N>
134
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
135
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
136
  template<bool Const>
137
- class elements_view<V, N>::iterator { // exposition only
138
- using Base = conditional_t<Const, const V, V>; // exposition only
 
 
 
 
139
 
140
- iterator_t<Base> current_ = iterator_t<Base>();
141
  public:
142
- using iterator_category = typename iterator_traits<iterator_t<Base>>::iterator_category;
 
143
  using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
144
  using difference_type = range_difference_t<Base>;
145
 
146
- iterator() = default;
147
  constexpr explicit iterator(iterator_t<Base> current);
148
  constexpr iterator(iterator<!Const> i)
149
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
150
 
151
- constexpr iterator_t<Base> base() const&
152
- requires copyable<iterator_t<Base>>;
153
  constexpr iterator_t<Base> base() &&;
154
 
155
  constexpr decltype(auto) operator*() const
156
- { return get<N>(*current_); }
157
 
158
  constexpr iterator& operator++();
159
- constexpr void operator++(int) requires (!forward_range<Base>);
160
  constexpr iterator operator++(int) requires forward_range<Base>;
161
 
162
  constexpr iterator& operator--() requires bidirectional_range<Base>;
163
  constexpr iterator operator--(int) requires bidirectional_range<Base>;
164
 
@@ -167,20 +172,20 @@ namespace std::ranges {
167
  constexpr iterator& operator-=(difference_type x)
168
  requires random_access_range<Base>;
169
 
170
  constexpr decltype(auto) operator[](difference_type n) const
171
  requires random_access_range<Base>
172
- { return get<N>(*(current_ + n)); }
173
 
174
  friend constexpr bool operator==(const iterator& x, const iterator& y)
175
  requires equality_comparable<iterator_t<Base>>;
176
 
177
  friend constexpr bool operator<(const iterator& x, const iterator& y)
178
  requires random_access_range<Base>;
179
  friend constexpr bool operator>(const iterator& x, const iterator& y)
180
  requires random_access_range<Base>;
181
- friend constexpr bool operator<=(const iterator& y, const iterator& y)
182
  requires random_access_range<Base>;
183
  friend constexpr bool operator>=(const iterator& x, const iterator& y)
184
  requires random_access_range<Base>;
185
  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
186
  requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
@@ -190,15 +195,51 @@ namespace std::ranges {
190
  friend constexpr iterator operator+(difference_type x, const iterator& y)
191
  requires random_access_range<Base>;
192
  friend constexpr iterator operator-(const iterator& x, difference_type y)
193
  requires random_access_range<Base>;
194
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
195
- requires random_access_range<Base>;
196
  };
197
  }
198
  ```
199
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  ``` cpp
201
  constexpr explicit iterator(iterator_t<Base> current);
202
  ```
203
 
204
  *Effects:* Initializes *current\_* with `std::move(current)`.
@@ -209,12 +250,11 @@ constexpr iterator(iterator<!Const> i)
209
  ```
210
 
211
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
212
 
213
  ``` cpp
214
- constexpr iterator_t<Base> base() const&
215
- requires copyable<iterator_t<Base>>;
216
  ```
217
 
218
  *Effects:* Equivalent to: `return `*`current_`*`;`
219
 
220
  ``` cpp
@@ -233,11 +273,11 @@ constexpr iterator& operator++();
233
  ++current_;
234
  return *this;
235
  ```
236
 
237
  ``` cpp
238
- constexpr void operator++(int) requires (!forward_range<Base>);
239
  ```
240
 
241
  *Effects:* Equivalent to: `++`*`current_`*.
242
 
243
  ``` cpp
@@ -274,11 +314,11 @@ auto temp = *this;
274
  --current_;
275
  return temp;
276
  ```
277
 
278
  ``` cpp
279
- constexpr iterator& operator+=(difference_type n);
280
  requires random_access_range<Base>;
281
  ```
282
 
283
  *Effects:* Equivalent to:
284
 
@@ -345,62 +385,68 @@ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
345
  ``` cpp
346
  friend constexpr iterator operator+(const iterator& x, difference_type y)
347
  requires random_access_range<Base>;
348
  ```
349
 
350
- *Effects:* Equivalent to: `return iterator{x} += y;`
351
 
352
  ``` cpp
353
  friend constexpr iterator operator+(difference_type x, const iterator& y)
354
  requires random_access_range<Base>;
355
  ```
356
 
357
  *Effects:* Equivalent to: `return y + x;`
358
 
359
  ``` cpp
360
- constexpr iterator operator-(const iterator& x, difference_type y)
361
  requires random_access_range<Base>;
362
  ```
363
 
364
- *Effects:* Equivalent to: `return iterator{x} -= y;`
365
 
366
  ``` cpp
367
- constexpr difference_type operator-(const iterator& x, const iterator& y)
368
- requires random_access_range<Base>;
369
  ```
370
 
371
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
372
 
373
  #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
374
 
375
  ``` cpp
376
  namespace std::ranges {
377
  template<input_range V, size_t N>
378
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
379
- has-tuple-element<remove_reference_t<range_reference_t<V>>, N>
 
380
  template<bool Const>
381
- class elements_view<V, N>::sentinel { // exposition only
382
  private:
383
- using Base = conditional_t<Const, const V, V>; // exposition only
384
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
385
  public:
386
  sentinel() = default;
387
  constexpr explicit sentinel(sentinel_t<Base> end);
388
  constexpr sentinel(sentinel<!Const> other)
389
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
390
 
391
  constexpr sentinel_t<Base> base() const;
392
 
393
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
394
 
395
- friend constexpr range_difference_t<Base>
396
- operator-(const iterator<Const>& x, const sentinel& y)
397
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
398
 
399
- friend constexpr range_difference_t<Base>
400
- operator-(const sentinel& x, const iterator<Const>& y)
401
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
402
  };
403
  }
404
  ```
405
 
406
  ``` cpp
@@ -421,144 +467,30 @@ constexpr sentinel_t<Base> base() const;
421
  ```
422
 
423
  *Effects:* Equivalent to: `return `*`end_`*`;`
424
 
425
  ``` cpp
426
- friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
 
 
427
  ```
428
 
429
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
430
 
431
  ``` cpp
432
- friend constexpr range_difference_t<Base>
433
- operator-(const iterator<Const>& x, const sentinel& y)
434
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
435
  ```
436
 
437
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
438
 
439
  ``` cpp
440
- friend constexpr range_difference_t<Base>
441
- operator-(const sentinel& x, const iterator<Const>& y)
442
- requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
 
443
  ```
444
 
445
  *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
446
 
447
- <!-- Link reference definitions -->
448
- [basic.compound]: basic.md#basic.compound
449
- [concepts.equality]: concepts.md#concepts.equality
450
- [containers]: containers.md#containers
451
- [conv.rval]: expr.md#conv.rval
452
- [customization.point.object]: library.md#customization.point.object
453
- [dcl.array]: dcl.md#dcl.array
454
- [expr.const]: expr.md#expr.const
455
- [iterator.concept.bidir]: iterators.md#iterator.concept.bidir
456
- [iterator.concept.iterator]: iterators.md#iterator.concept.iterator
457
- [iterator.concept.output]: iterators.md#iterator.concept.output
458
- [iterator.concept.random.access]: iterators.md#iterator.concept.random.access
459
- [iterator.concept.sizedsentinel]: iterators.md#iterator.concept.sizedsentinel
460
- [iterator.concept.winc]: iterators.md#iterator.concept.winc
461
- [iterator.requirements.general]: iterators.md#iterator.requirements.general
462
- [namespace.std]: library.md#namespace.std
463
- [range.access]: #range.access
464
- [range.access.begin]: #range.access.begin
465
- [range.access.cbegin]: #range.access.cbegin
466
- [range.access.cend]: #range.access.cend
467
- [range.access.crbegin]: #range.access.crbegin
468
- [range.access.crend]: #range.access.crend
469
- [range.access.end]: #range.access.end
470
- [range.access.rbegin]: #range.access.rbegin
471
- [range.access.rend]: #range.access.rend
472
- [range.adaptor.object]: #range.adaptor.object
473
- [range.adaptors]: #range.adaptors
474
- [range.all]: #range.all
475
- [range.common]: #range.common
476
- [range.common.overview]: #range.common.overview
477
- [range.common.view]: #range.common.view
478
- [range.counted]: #range.counted
479
- [range.dangling]: #range.dangling
480
- [range.drop]: #range.drop
481
- [range.drop.overview]: #range.drop.overview
482
- [range.drop.view]: #range.drop.view
483
- [range.drop.while]: #range.drop.while
484
- [range.drop.while.overview]: #range.drop.while.overview
485
- [range.drop.while.view]: #range.drop.while.view
486
- [range.elements]: #range.elements
487
- [range.elements.iterator]: #range.elements.iterator
488
- [range.elements.overview]: #range.elements.overview
489
- [range.elements.sentinel]: #range.elements.sentinel
490
- [range.elements.view]: #range.elements.view
491
- [range.empty]: #range.empty
492
- [range.empty.overview]: #range.empty.overview
493
- [range.empty.view]: #range.empty.view
494
- [range.factories]: #range.factories
495
- [range.filter]: #range.filter
496
- [range.filter.iterator]: #range.filter.iterator
497
- [range.filter.overview]: #range.filter.overview
498
- [range.filter.sentinel]: #range.filter.sentinel
499
- [range.filter.view]: #range.filter.view
500
- [range.iota]: #range.iota
501
- [range.iota.iterator]: #range.iota.iterator
502
- [range.iota.overview]: #range.iota.overview
503
- [range.iota.sentinel]: #range.iota.sentinel
504
- [range.iota.view]: #range.iota.view
505
- [range.istream]: #range.istream
506
- [range.istream.iterator]: #range.istream.iterator
507
- [range.istream.overview]: #range.istream.overview
508
- [range.istream.view]: #range.istream.view
509
- [range.join]: #range.join
510
- [range.join.iterator]: #range.join.iterator
511
- [range.join.overview]: #range.join.overview
512
- [range.join.sentinel]: #range.join.sentinel
513
- [range.join.view]: #range.join.view
514
- [range.prim.cdata]: #range.prim.cdata
515
- [range.prim.data]: #range.prim.data
516
- [range.prim.empty]: #range.prim.empty
517
- [range.prim.size]: #range.prim.size
518
- [range.prim.ssize]: #range.prim.ssize
519
- [range.range]: #range.range
520
- [range.ref.view]: #range.ref.view
521
- [range.refinements]: #range.refinements
522
- [range.req]: #range.req
523
- [range.req.general]: #range.req.general
524
- [range.reverse]: #range.reverse
525
- [range.reverse.overview]: #range.reverse.overview
526
- [range.reverse.view]: #range.reverse.view
527
- [range.semi.wrap]: #range.semi.wrap
528
- [range.single]: #range.single
529
- [range.single.overview]: #range.single.overview
530
- [range.single.view]: #range.single.view
531
- [range.sized]: #range.sized
532
- [range.split]: #range.split
533
- [range.split.inner]: #range.split.inner
534
- [range.split.outer]: #range.split.outer
535
- [range.split.outer.value]: #range.split.outer.value
536
- [range.split.overview]: #range.split.overview
537
- [range.split.view]: #range.split.view
538
- [range.subrange]: #range.subrange
539
- [range.subrange.access]: #range.subrange.access
540
- [range.subrange.ctor]: #range.subrange.ctor
541
- [range.summary]: #range.summary
542
- [range.take]: #range.take
543
- [range.take.overview]: #range.take.overview
544
- [range.take.sentinel]: #range.take.sentinel
545
- [range.take.view]: #range.take.view
546
- [range.take.while]: #range.take.while
547
- [range.take.while.overview]: #range.take.while.overview
548
- [range.take.while.sentinel]: #range.take.while.sentinel
549
- [range.take.while.view]: #range.take.while.view
550
- [range.transform]: #range.transform
551
- [range.transform.iterator]: #range.transform.iterator
552
- [range.transform.overview]: #range.transform.overview
553
- [range.transform.sentinel]: #range.transform.sentinel
554
- [range.transform.view]: #range.transform.view
555
- [range.utility]: #range.utility
556
- [range.utility.helpers]: #range.utility.helpers
557
- [range.view]: #range.view
558
- [ranges]: #ranges
559
- [ranges.general]: #ranges.general
560
- [ranges.syn]: #ranges.syn
561
- [string.view]: strings.md#string.view
562
- [view.interface]: #view.interface
563
- [view.interface.members]: #view.interface.members
564
- [views.span]: containers.md#views.span
 
1
  ### Elements view <a id="range.elements">[[range.elements]]</a>
2
 
3
  #### Overview <a id="range.elements.overview">[[range.elements.overview]]</a>
4
 
5
+ `elements_view` takes a view of tuple-like values and a `size_t`, and
6
+ produces a view with a value-type of the Nᵗʰ element of the adapted
7
+ view’s value-type.
8
 
9
  The name `views::elements<N>` denotes a range adaptor object
10
  [[range.adaptor.object]]. Given a subexpression `E` and constant
11
  expression `N`, the expression `views::elements<N>(E)` is
12
  expression-equivalent to
 
14
 
15
  [*Example 1*:
16
 
17
  ``` cpp
18
  auto historical_figures = map{
19
+ pair{"Lovelace"sv, 1815},
20
  {"Turing"sv, 1912},
21
  {"Babbage"sv, 1791},
22
  {"Hamilton"sv, 1936}
23
  };
24
 
 
33
  }
34
  ```
35
 
36
  — *end example*]
37
 
38
+ `keys_view` is an alias for `elements_view<R, 0>`, and is useful for
39
+ extracting keys from associative containers.
40
 
41
  [*Example 2*:
42
 
43
  ``` cpp
44
+ auto names = historical_figures | views::keys;
45
  for (auto&& name : names) {
46
  cout << name << ' '; // prints Babbage Hamilton Lovelace Turing
47
  }
48
  ```
49
 
50
  — *end example*]
51
 
52
+ `values_view` is an alias for `elements_view<R, 1>`, and is useful for
53
+ extracting values from associative containers.
54
 
55
  [*Example 3*:
56
 
57
  ``` cpp
58
  auto is_even = [](const auto x) { return x % 2 == 0; };
59
+ cout << ranges::count_if(historical_figures | views::values, is_even); // prints 2
60
  ```
61
 
62
  — *end example*]
63
 
64
  #### Class template `elements_view` <a id="range.elements.view">[[range.elements.view]]</a>
65
 
66
  ``` cpp
67
  namespace std::ranges {
68
  template<class T, size_t N>
69
  concept has-tuple-element = // exposition only
70
+ tuple-like<T> && N < tuple_size_v<T>;
 
 
 
 
 
71
 
72
+ template<class T, size_t N>
73
+ concept returnable-element = // exposition only
74
+ is_reference_v<T> || move_constructible<tuple_element_t<N, T>>;
75
 
76
  template<input_range V, size_t N>
77
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
78
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
79
+ returnable-element<range_reference_t<V>, N>
80
  class elements_view : public view_interface<elements_view<V, N>> {
81
  public:
82
+ elements_view() requires default_initializable<V> = default;
83
  constexpr explicit elements_view(V base);
84
 
85
  constexpr V base() const & requires copy_constructible<V> { return base_; }
86
  constexpr V base() && { return std::move(base_); }
87
 
88
  constexpr auto begin() requires (!simple-view<V>)
89
  { return iterator<false>(ranges::begin(base_)); }
90
 
91
+ constexpr auto begin() const requires range<const V>
92
  { return iterator<true>(ranges::begin(base_)); }
93
 
94
+ constexpr auto end() requires (!simple-view<V> && !common_range<V>)
95
  { return sentinel<false>{ranges::end(base_)}; }
96
 
97
+ constexpr auto end() requires (!simple-view<V> && common_range<V>)
98
  { return iterator<false>{ranges::end(base_)}; }
99
 
100
  constexpr auto end() const requires range<const V>
101
  { return sentinel<true>{ranges::end(base_)}; }
102
 
 
109
  constexpr auto size() const requires sized_range<const V>
110
  { return ranges::size(base_); }
111
 
112
  private:
113
  // [range.elements.iterator], class template elements_view::iterator
114
+ template<bool> class iterator; // exposition only
115
+
116
  // [range.elements.sentinel], class template elements_view::sentinel
117
+ template<bool> class sentinel; // exposition only
118
+
119
  V base_ = V(); // exposition only
120
  };
121
  }
122
  ```
123
 
 
131
 
132
  ``` cpp
133
  namespace std::ranges {
134
  template<input_range V, size_t N>
135
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
136
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
137
+ returnable-element<range_reference_t<V>, N>
138
  template<bool Const>
139
+ class elements_view<V, N>::iterator {
140
+ using Base = maybe-const<Const, V>; // exposition only
141
+
142
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
143
+
144
+ static constexpr decltype(auto) get-element(const iterator_t<Base>& i); // exposition only
145
 
 
146
  public:
147
+ using iterator_concept = see below;
148
+ using iterator_category = see below; // not always present
149
  using value_type = remove_cvref_t<tuple_element_t<N, range_value_t<Base>>>;
150
  using difference_type = range_difference_t<Base>;
151
 
152
+ iterator() requires default_initializable<iterator_t<Base>> = default;
153
  constexpr explicit iterator(iterator_t<Base> current);
154
  constexpr iterator(iterator<!Const> i)
155
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
156
 
157
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
158
  constexpr iterator_t<Base> base() &&;
159
 
160
  constexpr decltype(auto) operator*() const
161
+ { return get-element(current_); }
162
 
163
  constexpr iterator& operator++();
164
+ constexpr void operator++(int);
165
  constexpr iterator operator++(int) requires forward_range<Base>;
166
 
167
  constexpr iterator& operator--() requires bidirectional_range<Base>;
168
  constexpr iterator operator--(int) requires bidirectional_range<Base>;
169
 
 
172
  constexpr iterator& operator-=(difference_type x)
173
  requires random_access_range<Base>;
174
 
175
  constexpr decltype(auto) operator[](difference_type n) const
176
  requires random_access_range<Base>
177
+ { return get-element(current_ + n); }
178
 
179
  friend constexpr bool operator==(const iterator& x, const iterator& y)
180
  requires equality_comparable<iterator_t<Base>>;
181
 
182
  friend constexpr bool operator<(const iterator& x, const iterator& y)
183
  requires random_access_range<Base>;
184
  friend constexpr bool operator>(const iterator& x, const iterator& y)
185
  requires random_access_range<Base>;
186
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
187
  requires random_access_range<Base>;
188
  friend constexpr bool operator>=(const iterator& x, const iterator& y)
189
  requires random_access_range<Base>;
190
  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
191
  requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
 
195
  friend constexpr iterator operator+(difference_type x, const iterator& y)
196
  requires random_access_range<Base>;
197
  friend constexpr iterator operator-(const iterator& x, difference_type y)
198
  requires random_access_range<Base>;
199
  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
200
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
201
  };
202
  }
203
  ```
204
 
205
+ The member *typedef-name* `iterator_concept` is defined as follows:
206
+
207
+ - If *`Base`* models `random_access_range`, then `iterator_concept`
208
+ denotes `random_access_iterator_tag`.
209
+ - Otherwise, if *`Base`* models `bidirectional_range`, then
210
+ `iterator_concept` denotes `bidirectional_iterator_tag`.
211
+ - Otherwise, if *`Base`* models `forward_range`, then `iterator_concept`
212
+ denotes `forward_iterator_tag`.
213
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
214
+
215
+ The member *typedef-name* `iterator_category` is defined if and only if
216
+ *`Base`* models `forward_range`. In that case, `iterator_category` is
217
+ defined as follows: Let `C` denote the type
218
+ `iterator_traits<iterator_t<Base>>::iterator_category`.
219
+
220
+ - If `std::get<N>(*current_)` is an rvalue, `iterator_category` denotes
221
+ `input_iterator_tag`.
222
+ - Otherwise, if `C` models `derived_from<random_access_iterator_tag>`,
223
+ `iterator_category` denotes `random_access_iterator_tag`.
224
+ - Otherwise, `iterator_category` denotes `C`.
225
+
226
+ ``` cpp
227
+ static constexpr decltype(auto) get-element(const iterator_t<Base>& i);
228
+ ```
229
+
230
+ *Effects:* Equivalent to:
231
+
232
+ ``` cpp
233
+ if constexpr (is_reference_v<range_reference_t<Base>>) {
234
+ return std::get<N>(*i);
235
+ } else {
236
+ using E = remove_cv_t<tuple_element_t<N, range_reference_t<Base>>>;
237
+ return static_cast<E>(std::get<N>(*i));
238
+ }
239
+ ```
240
+
241
  ``` cpp
242
  constexpr explicit iterator(iterator_t<Base> current);
243
  ```
244
 
245
  *Effects:* Initializes *current\_* with `std::move(current)`.
 
250
  ```
251
 
252
  *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
253
 
254
  ``` cpp
255
+ constexpr const iterator_t<Base>& base() const & noexcept;
 
256
  ```
257
 
258
  *Effects:* Equivalent to: `return `*`current_`*`;`
259
 
260
  ``` cpp
 
273
  ++current_;
274
  return *this;
275
  ```
276
 
277
  ``` cpp
278
+ constexpr void operator++(int);
279
  ```
280
 
281
  *Effects:* Equivalent to: `++`*`current_`*.
282
 
283
  ``` cpp
 
314
  --current_;
315
  return temp;
316
  ```
317
 
318
  ``` cpp
319
+ constexpr iterator& operator+=(difference_type n)
320
  requires random_access_range<Base>;
321
  ```
322
 
323
  *Effects:* Equivalent to:
324
 
 
385
  ``` cpp
386
  friend constexpr iterator operator+(const iterator& x, difference_type y)
387
  requires random_access_range<Base>;
388
  ```
389
 
390
+ *Effects:* Equivalent to: `return `*`iterator`*`{x} += y;`
391
 
392
  ``` cpp
393
  friend constexpr iterator operator+(difference_type x, const iterator& y)
394
  requires random_access_range<Base>;
395
  ```
396
 
397
  *Effects:* Equivalent to: `return y + x;`
398
 
399
  ``` cpp
400
+ friend constexpr iterator operator-(const iterator& x, difference_type y)
401
  requires random_access_range<Base>;
402
  ```
403
 
404
+ *Effects:* Equivalent to: `return `*`iterator`*`{x} -= y;`
405
 
406
  ``` cpp
407
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
408
+ requires sized_sentinel_for<iterator_t<Base>, iterator_t<Base>>;
409
  ```
410
 
411
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`current_`*`;`
412
 
413
  #### Class template `elements_view::sentinel` <a id="range.elements.sentinel">[[range.elements.sentinel]]</a>
414
 
415
  ``` cpp
416
  namespace std::ranges {
417
  template<input_range V, size_t N>
418
  requires view<V> && has-tuple-element<range_value_t<V>, N> &&
419
+ has-tuple-element<remove_reference_t<range_reference_t<V>>, N> &&
420
+ returnable-element<range_reference_t<V>, N>
421
  template<bool Const>
422
+ class elements_view<V, N>::sentinel {
423
  private:
424
+ using Base = maybe-const<Const, V>; // exposition only
425
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
426
+
427
  public:
428
  sentinel() = default;
429
  constexpr explicit sentinel(sentinel_t<Base> end);
430
  constexpr sentinel(sentinel<!Const> other)
431
  requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>;
432
 
433
  constexpr sentinel_t<Base> base() const;
434
 
435
+ template<bool OtherConst>
436
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
437
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
438
 
439
+ template<bool OtherConst>
440
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
441
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
442
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
443
 
444
+ template<bool OtherConst>
445
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
446
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
447
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
448
  };
449
  }
450
  ```
451
 
452
  ``` cpp
 
467
  ```
468
 
469
  *Effects:* Equivalent to: `return `*`end_`*`;`
470
 
471
  ``` cpp
472
+ template<bool OtherConst>
473
+ requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
474
+ friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
475
  ```
476
 
477
  *Effects:* Equivalent to: `return x.`*`current_`*` == y.`*`end_`*`;`
478
 
479
  ``` cpp
480
+ template<bool OtherConst>
481
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
482
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
483
+ operator-(const iterator<OtherConst>& x, const sentinel& y);
484
  ```
485
 
486
  *Effects:* Equivalent to: `return x.`*`current_`*` - y.`*`end_`*`;`
487
 
488
  ``` cpp
489
+ template<bool OtherConst>
490
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
491
+ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
492
+ operator-(const sentinel& x, const iterator<OtherConst>& y);
493
  ```
494
 
495
  *Effects:* Equivalent to: `return x.`*`end_`*` - y.`*`current_`*`;`
496