From Jason Turner

[range.adaptors]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpo_3wurqs/{from.md → to.md} +1520 -75
tmp/tmpo_3wurqs/{from.md → to.md} RENAMED
@@ -157,11 +157,11 @@ exactly like `optional<T>` with the following differences:
157
  - Otherwise, `movable-box<T>` should store only a `T` if either `T`
158
  models `movable` or `is_nothrow_move_constructible_v<T>` is `true`.
159
 
160
  ### Non-propagating cache <a id="range.nonprop.cache">[[range.nonprop.cache]]</a>
161
 
162
- Some types in subclause [[range.adaptors]] are specified in terms of an
163
  exposition-only class template *`non-propagating-{}cache`*.
164
  `non-propagating-cache<T>` behaves exactly like `optional<T>` with the
165
  following differences:
166
 
167
  - `non-propagating-cache<T>` constrains its type parameter `T` with
@@ -236,10 +236,20 @@ namespace std::ranges {
236
 
237
  template<class T>
238
  constexpr T& as-lvalue(T&& t) { // exposition only
239
  return static_cast<T&>(t);
240
  }
 
 
 
 
 
 
 
 
 
 
241
  }
242
  ```
243
 
244
  ### All view <a id="range.all">[[range.all]]</a>
245
 
@@ -283,10 +293,13 @@ namespace std::ranges {
283
  { return ranges::empty(*r_); }
284
 
285
  constexpr auto size() const requires sized_range<R>
286
  { return ranges::size(*r_); }
287
 
 
 
 
288
  constexpr auto data() const requires contiguous_range<R>
289
  { return ranges::data(*r_); }
290
  };
291
 
292
  template<class R>
@@ -356,10 +369,15 @@ namespace std::ranges {
356
  constexpr auto size() requires sized_range<R>
357
  { return ranges::size(r_); }
358
  constexpr auto size() const requires sized_range<const R>
359
  { return ranges::size(r_); }
360
 
 
 
 
 
 
361
  constexpr auto data() requires contiguous_range<R>
362
  { return ranges::data(r_); }
363
  constexpr auto data() const requires contiguous_range<const R>
364
  { return ranges::data(r_); }
365
  };
@@ -384,11 +402,11 @@ to replace copying with moving.
384
  The name `views::as_rvalue` denotes a range adaptor object
385
  [[range.adaptor.object]]. Let `E` be an expression and let `T` be
386
  `decltype((E))`. The expression `views::as_rvalue(E)` is
387
  expression-equivalent to:
388
 
389
- - `views::all(E)` if
390
  `same_as<range_rvalue_reference_t<T>, range_reference_t<T>>` is
391
  `true`.
392
  - Otherwise, `as_rvalue_view(E)`.
393
 
394
  [*Example 1*:
@@ -438,10 +456,15 @@ namespace std::ranges {
438
  }
439
  }
440
 
441
  constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
442
  constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
 
 
 
 
 
443
  };
444
 
445
  template<class R>
446
  as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>;
447
  }
@@ -825,10 +848,15 @@ namespace std::ranges {
825
  regular_invocable<const F&, range_reference_t<const V>>;
826
 
827
  constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
828
  constexpr auto size() const requires sized_range<const V>
829
  { return ranges::size(base_); }
 
 
 
 
 
830
  };
831
 
832
  template<class R, class F>
833
  transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
834
  }
@@ -1408,10 +1436,26 @@ namespace std::ranges {
1408
 
1409
  constexpr auto size() const requires sized_range<const V> {
1410
  auto n = ranges::size(base_);
1411
  return ranges::min(n, static_cast<decltype(n)>(count_));
1412
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1413
  };
1414
 
1415
  template<class R>
1416
  take_view(R&&, range_difference_t<R>)
1417
  -> take_view<views::all_t<R>>;
@@ -1661,12 +1705,12 @@ expression `views::drop(E, F)` is expression-equivalent to:
1661
  then
1662
  `U(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::end(E))`,
1663
  except that `E` is evaluated only once, where `U` is
1664
  `span<typename T::element_type>` if `T` is a specialization of `span`
1665
  and `T` otherwise.
1666
- - Otherwise, if `T` is a specialization of `subrange` [[range.subrange]]
1667
- that models `random_access_range` and `sized_range`, then
1668
  `T(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::{}end(E),
1669
  to-unsigned-like(ranges::distance(E) -
1670
  std::min<D>(ranges::distance(E), F)))`, except that `E` and `F` are
1671
  each evaluated only once.
1672
  - Otherwise, if `T` is a specialization of `repeat_view`
@@ -1727,10 +1771,20 @@ namespace std::ranges {
1727
  const auto s = ranges::size(base_);
1728
  const auto c = static_cast<decltype(s)>(count_);
1729
  return s < c ? 0 : s - c;
1730
  }
1731
 
 
 
 
 
 
 
 
 
 
 
1732
  private:
1733
  V base_ = V(); // exposition only
1734
  range_difference_t<V> count_ = 0; // exposition only
1735
  };
1736
 
@@ -2233,11 +2287,11 @@ friend constexpr void iter_swap(const iterator& x, const iterator& y)
2233
  noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
2234
  requires indirectly_swappable<InnerIter>;
2235
  ```
2236
 
2237
  *Effects:* Equivalent to:
2238
- `return ranges::iter_swap(*x.`*`inner_`*`, *y.`*`inner_`*`);`
2239
 
2240
  #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
2241
 
2242
  ``` cpp
2243
  namespace std::ranges {
@@ -2312,23 +2366,17 @@ for (char c : vs | views::join_with('-')) {
2312
 
2313
  #### Class template `join_with_view` <a id="range.join.with.view">[[range.join.with.view]]</a>
2314
 
2315
  ``` cpp
2316
  namespace std::ranges {
2317
- template<class R, class P>
2318
- concept compatible-joinable-ranges = // exposition only
2319
- common_with<range_value_t<R>, range_value_t<P>> &&
2320
- common_reference_with<range_reference_t<R>, range_reference_t<P>> &&
2321
- common_reference_with<range_rvalue_reference_t<R>, range_rvalue_reference_t<P>>;
2322
-
2323
  template<class R>
2324
  concept bidirectional-common = bidirectional_range<R> && common_range<R>; // exposition only
2325
 
2326
  template<input_range V, forward_range Pattern>
2327
  requires view<V> && input_range<range_reference_t<V>>
2328
  && view<Pattern>
2329
- && compatible-joinable-ranges<range_reference_t<V>, Pattern>
2330
  class join_with_view : public view_interface<join_with_view<V, Pattern>> {
2331
  using InnerRng = range_reference_t<V>; // exposition only
2332
 
2333
  V base_ = V(); // exposition only
2334
  non-propagating-cache<iterator_t<V>> outer_it_; // exposition only, present only
@@ -2370,11 +2418,12 @@ namespace std::ranges {
2370
  }
2371
  constexpr auto begin() const
2372
  requires forward_range<const V> &&
2373
  forward_range<const Pattern> &&
2374
  is_reference_v<range_reference_t<const V>> &&
2375
- input_range<range_reference_t<const V>> {
 
2376
  return iterator<true>{*this, ranges::begin(base_)};
2377
  }
2378
 
2379
  constexpr auto end() {
2380
  if constexpr (forward_range<V> &&
@@ -2385,11 +2434,12 @@ namespace std::ranges {
2385
  return sentinel<simple-view<V> && simple-view<Pattern>>{*this};
2386
  }
2387
  constexpr auto end() const
2388
  requires forward_range<const V> && forward_range<const Pattern> &&
2389
  is_reference_v<range_reference_t<const V>> &&
2390
- input_range<range_reference_t<const V>> {
 
2391
  using InnerConstRng = range_reference_t<const V>;
2392
  if constexpr (forward_range<InnerConstRng> &&
2393
  common_range<const V> && common_range<InnerConstRng>)
2394
  return iterator<true>{*this, ranges::end(base_)};
2395
  else
@@ -2427,11 +2477,11 @@ and *pattern\_* with `views::single(std::move(e))`.
2427
 
2428
  ``` cpp
2429
  namespace std::ranges {
2430
  template<input_range V, forward_range Pattern>
2431
  requires view<V> && input_range<range_reference_t<V>>
2432
- && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
2433
  template<bool Const>
2434
  class join_with_view<V, Pattern>::iterator {
2435
  using Parent = maybe-const<Const, join_with_view>; // exposition only
2436
  using Base = maybe-const<Const, V>; // exposition only
2437
  using InnerBase = range_reference_t<Base>; // exposition only
@@ -2530,11 +2580,11 @@ as follows:
2530
  iter_reference_t<PatternIter>>>
2531
  ```
2532
 
2533
  is `false`, `iterator_category` denotes `input_iterator_tag`.
2534
  - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
2535
- `derived_from<bidirectional_iterator_category>` and *`InnerBase`* and
2536
  *`PatternBase`* each model `common_range`, `iterator_category` denotes
2537
  `bidirectional_iterator_tag`.
2538
  - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
2539
  `derived_from<forward_iterator_tag>`, `iterator_category` denotes
2540
  `forward_iterator_tag`.
@@ -2598,20 +2648,20 @@ constexpr void satisfy();
2598
  ``` cpp
2599
  while (true) {
2600
  if (inner_it_.index() == 0) {
2601
  if (std::get<0>(inner_it_) != ranges::end(parent_->pattern_))
2602
  break;
2603
- inner_it_.emplace<1>(ranges::begin(update-inner()));
2604
  } else {
2605
  if (std::get<1>(inner_it_) != ranges::end(get-inner()))
2606
  break;
2607
  if (++outer() == ranges::end(parent_->base_)) {
2608
  if constexpr (ref-is-glvalue)
2609
- inner_it_.emplace<0>();
2610
  break;
2611
  }
2612
- inner_it_.emplace<0>(ranges::begin(parent_->pattern_));
2613
  }
2614
  }
2615
  ```
2616
 
2617
  [*Note 1*: `join_with_view` iterators use the *satisfy* function to
@@ -2628,11 +2678,11 @@ constexpr explicit iterator(Parent& parent)
2628
  first overload, also initializes *outer_it\_* with `std::move(outer)`.
2629
  Then, equivalent to:
2630
 
2631
  ``` cpp
2632
  if (outer() != ranges::end(parent_->base_)) {
2633
- inner_it_.emplace<1>(ranges::begin(update-inner()));
2634
  satisfy();
2635
  }
2636
  ```
2637
 
2638
  ``` cpp
@@ -2645,13 +2695,13 @@ constexpr iterator(iterator<!Const> i)
2645
  *Effects:* Initializes *outer_it\_* with `std::move(i.`*`outer_it_`*`)`
2646
  and *parent\_* with `i.`*`parent_`*. Then, equivalent to:
2647
 
2648
  ``` cpp
2649
  if (i.inner_it_.index() == 0)
2650
- inner_it_.emplace<0>(std::get<0>(std::move(i.inner_it_)));
2651
  else
2652
- inner_it_.emplace<1>(std::get<1>(std::move(i.inner_it_)));
2653
  ```
2654
 
2655
  [*Note 2*: `Const` can only be `true` when *Base* models
2656
  `forward_range`. — *end note*]
2657
 
@@ -2707,27 +2757,27 @@ constexpr iterator& operator--()
2707
  *Effects:* Equivalent to:
2708
 
2709
  ``` cpp
2710
  if (outer_it_ == ranges::end(parent_->base_)) {
2711
  auto&& inner = *--outer_it_;
2712
- inner_it_.emplace<1>(ranges::end(inner));
2713
  }
2714
 
2715
  while (true) {
2716
  if (inner_it_.index() == 0) {
2717
  auto& it = std::get<0>(inner_it_);
2718
  if (it == ranges::begin(parent_->pattern_)) {
2719
  auto&& inner = *--outer_it_;
2720
- inner_it_.emplace<1>(ranges::end(inner));
2721
  } else {
2722
  break;
2723
  }
2724
  } else {
2725
  auto& it = std::get<1>(inner_it_);
2726
  auto&& inner = *outer_it_;
2727
  if (it == ranges::begin(inner)) {
2728
- inner_it_.emplace<0>(ranges::end(parent_->pattern_));
2729
  } else {
2730
  break;
2731
  }
2732
  }
2733
  }
@@ -2765,11 +2815,11 @@ return x.outer_it_ == y.outer_it_ && x.inner_it_ == y.inner_it_;
2765
 
2766
  ``` cpp
2767
  namespace std::ranges {
2768
  template<input_range V, forward_range Pattern>
2769
  requires view<V> && input_range<range_reference_t<V>>
2770
- && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>
2771
  template<bool Const>
2772
  class join_with_view<V, Pattern>::sentinel {
2773
  using Parent = maybe-const<Const, join_with_view>; // exposition only
2774
  using Base = maybe-const<Const, V>; // exposition only
2775
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
@@ -3014,12 +3064,13 @@ constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
3014
  ``` cpp
3015
  constexpr outer-iterator(outer-iterator<!Const> i)
3016
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
3017
  ```
3018
 
3019
- *Effects:* Initializes *parent\_* with `i.`*`parent_`* and *current\_*
3020
- with `std::move(i.`*`current_`*`)`.
 
3021
 
3022
  ``` cpp
3023
  constexpr value_type operator*() const;
3024
  ```
3025
 
@@ -3094,14 +3145,13 @@ namespace std::ranges {
3094
  struct lazy_split_view<V, Pattern>::outer-iterator<Const>::value_type
3095
  : view_interface<value_type> {
3096
  private:
3097
  outer-iterator i_ = outer-iterator(); // exposition only
3098
 
3099
- public:
3100
- value_type() = default;
3101
- constexpr explicit value_type(outer-iterator i);
3102
 
 
3103
  constexpr inner-iterator<Const> begin() const;
3104
  constexpr default_sentinel_t end() const noexcept;
3105
  };
3106
  }
3107
  ```
@@ -3139,11 +3189,11 @@ namespace std::ranges {
3139
  using Base = maybe-const<Const, V>; // exposition only
3140
  outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
3141
  bool incremented_ = false; // exposition only
3142
 
3143
  public:
3144
- using iterator_concept = typename outer-iterator<Const>::iterator_concept;
3145
 
3146
  using iterator_category = see belownc; // present only if Base
3147
  // models forward_range
3148
  using value_type = range_value_t<Base>;
3149
  using difference_type = range_difference_t<Base>;
@@ -3434,17 +3484,17 @@ constexpr iterator(split_view& parent, iterator_t<V> current, subrange<iterator_
3434
 
3435
  ``` cpp
3436
  constexpr iterator_t<V> base() const;
3437
  ```
3438
 
3439
- *Effects:* Equivalent to `return `*`cur_`*`;`
3440
 
3441
  ``` cpp
3442
  constexpr value_type operator*() const;
3443
  ```
3444
 
3445
- *Effects:* Equivalent to `return {`*`cur_`*`, `*`next_`*`.begin()};`
3446
 
3447
  ``` cpp
3448
  constexpr iterator& operator++();
3449
  ```
3450
 
@@ -3519,10 +3569,798 @@ friend constexpr bool operator==(const iterator& x, const sentinel& y);
3519
  ```
3520
 
3521
  *Effects:* Equivalent to:
3522
  `return x.`*`cur_`*` == y.`*`end_`*` && !x.`*`trailing_empty_`*`;`
3523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3524
  ### Counted view <a id="range.counted">[[range.counted]]</a>
3525
 
3526
  A counted view presents a view of the elements of the counted range
3527
  [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
3528
  non-negative integer `n`.
@@ -3599,11 +4437,11 @@ namespace std::ranges {
3599
  constexpr explicit common_view(V r);
3600
 
3601
  constexpr V base() const & requires copy_constructible<V> { return base_; }
3602
  constexpr V base() && { return std::move(base_); }
3603
 
3604
- constexpr auto begin() {
3605
  if constexpr (random_access_range<V> && sized_range<V>)
3606
  return ranges::begin(base_);
3607
  else
3608
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
3609
  }
@@ -3613,11 +4451,11 @@ namespace std::ranges {
3613
  return ranges::begin(base_);
3614
  else
3615
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
3616
  }
3617
 
3618
- constexpr auto end() {
3619
  if constexpr (random_access_range<V> && sized_range<V>)
3620
  return ranges::begin(base_) + ranges::distance(base_);
3621
  else
3622
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
3623
  }
@@ -3633,10 +4471,17 @@ namespace std::ranges {
3633
  return ranges::size(base_);
3634
  }
3635
  constexpr auto size() const requires sized_range<const V> {
3636
  return ranges::size(base_);
3637
  }
 
 
 
 
 
 
 
3638
  };
3639
 
3640
  template<class R>
3641
  common_view(R&&) -> common_view<views::all_t<R>>;
3642
  }
@@ -3658,25 +4503,20 @@ iterates the same elements in reverse order.
3658
  The name `views::reverse` denotes a range adaptor object
3659
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
3660
  `views::reverse(E)` is expression-equivalent to:
3661
 
3662
  - If the type of `E` is a (possibly cv-qualified) specialization of
3663
- `reverse_view`, equivalent to `E.base()`.
3664
  - Otherwise, if the type of `E` is cv
3665
  `subrange<reverse_iterator<I>, reverse_iterator<I>, K>` for some
3666
  iterator type `I` and value `K` of type `subrange_kind`,
3667
- - if `K` is `subrange_kind::sized`, equivalent to:
3668
- ``` cpp
3669
- subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())
3670
- ```
3671
- - otherwise, equivalent to:
3672
- ``` cpp
3673
- subrange<I, I, K>(E.end().base(), E.begin().base())
3674
- ```
3675
 
3676
  However, in either case `E` is evaluated only once.
3677
- - Otherwise, equivalent to `reverse_view{E}`.
3678
 
3679
  [*Example 1*:
3680
 
3681
  ``` cpp
3682
  vector<int> is {0,1,2,3,4};
@@ -3716,10 +4556,17 @@ namespace std::ranges {
3716
  }
3717
 
3718
  constexpr auto size() const requires sized_range<const V> {
3719
  return ranges::size(base_);
3720
  }
 
 
 
 
 
 
 
3721
  };
3722
 
3723
  template<class R>
3724
  reverse_view(R&&) -> reverse_view<views::all_t<R>>;
3725
  }
@@ -3820,10 +4667,15 @@ namespace std::ranges {
3820
  constexpr auto end() requires (!simple-view<V>) { return ranges::cend(base_); }
3821
  constexpr auto end() const requires range<const V> { return ranges::cend(base_); }
3822
 
3823
  constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
3824
  constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
 
 
 
 
 
3825
  };
3826
 
3827
  template<class R>
3828
  as_const_view(R&&) -> as_const_view<views::all_t<R>>;
3829
  }
@@ -3944,10 +4796,16 @@ namespace std::ranges {
3944
  { return ranges::size(base_); }
3945
 
3946
  constexpr auto size() const requires sized_range<const V>
3947
  { return ranges::size(base_); }
3948
 
 
 
 
 
 
 
3949
  private:
3950
  // [range.elements.iterator], class template elements_view::iterator
3951
  template<bool> class iterator; // exposition only
3952
 
3953
  // [range.elements.sentinel], class template elements_view::sentinel
@@ -4336,13 +5194,13 @@ friend constexpr range_difference_t<maybe-const<OtherConst, V>>
4336
  #### Overview <a id="range.enumerate.overview">[[range.enumerate.overview]]</a>
4337
 
4338
  `enumerate_view` is a view whose elements represent both the position
4339
  and value from a sequence of elements.
4340
 
4341
- The name `views::enumerate` denotes a range adaptor object. Given a
4342
- subexpression `E`, the expression `views::enumerate(E)` is
4343
- expression-equivalent to
4344
  `enumerate_view<views::all_t<decltype((E))>>(E)`.
4345
 
4346
  [*Example 1*:
4347
 
4348
  ``` cpp
@@ -4378,27 +5236,32 @@ namespace std::ranges {
4378
  { return iterator<false>(ranges::begin(base_), 0); }
4379
  constexpr auto begin() const requires range-with-movable-references<const V>
4380
  { return iterator<true>(ranges::begin(base_), 0); }
4381
 
4382
  constexpr auto end() requires (!simple-view<V>) {
4383
- if constexpr (common_range<V> && sized_range<V>)
4384
  return iterator<false>(ranges::end(base_), ranges::distance(base_));
4385
  else
4386
  return sentinel<false>(ranges::end(base_));
4387
  }
4388
  constexpr auto end() const requires range-with-movable-references<const V> {
4389
- if constexpr (common_range<const V> && sized_range<const V>)
4390
  return iterator<true>(ranges::end(base_), ranges::distance(base_));
4391
  else
4392
  return sentinel<true>(ranges::end(base_));
4393
  }
4394
 
4395
  constexpr auto size() requires sized_range<V>
4396
  { return ranges::size(base_); }
4397
  constexpr auto size() const requires sized_range<const V>
4398
  { return ranges::size(base_); }
4399
 
 
 
 
 
 
4400
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4401
  constexpr V base() && { return std::move(base_); }
4402
  };
4403
 
4404
  template<class R>
@@ -4474,11 +5337,11 @@ namespace std::ranges {
4474
  requires random_access_range<Base>;
4475
  friend constexpr iterator operator+(difference_type x, const iterator& y)
4476
  requires random_access_range<Base>;
4477
  friend constexpr iterator operator-(const iterator& x, difference_type y)
4478
  requires random_access_range<Base>;
4479
- friend constexpr difference_type operator-(const iterator& x, const iterator& y);
4480
 
4481
  friend constexpr auto iter_move(const iterator& i)
4482
  noexcept(noexcept(ranges::iter_move(i.current_)) &&
4483
  is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>) {
4484
  return tuple<difference_type,
@@ -4656,11 +5519,11 @@ auto temp = x;
4656
  temp -= y;
4657
  return temp;
4658
  ```
4659
 
4660
  ``` cpp
4661
- friend constexpr difference_type operator-(const iterator& x, const iterator& y);
4662
  ```
4663
 
4664
  *Effects:* Equivalent to: `return x.`*`pos_`*` - y.`*`pos_`*`;`
4665
 
4666
  #### Class template `enumerate_view::sentinel` <a id="range.enumerate.sentinel">[[range.enumerate.sentinel]]</a>
@@ -4867,20 +5730,10 @@ return apply([](auto... sizes) {
4867
 
4868
  #### Class template `zip_view::iterator` <a id="range.zip.iterator">[[range.zip.iterator]]</a>
4869
 
4870
  ``` cpp
4871
  namespace std::ranges {
4872
- template<bool Const, class... Views>
4873
- concept all-random-access = // exposition only
4874
- (random_access_range<maybe-const<Const, Views>> && ...);
4875
- template<bool Const, class... Views>
4876
- concept all-bidirectional = // exposition only
4877
- (bidirectional_range<maybe-const<Const, Views>> && ...);
4878
- template<bool Const, class... Views>
4879
- concept all-forward = // exposition only
4880
- (forward_range<maybe-const<Const, Views>> && ...);
4881
-
4882
  template<input_range... Views>
4883
  requires (view<Views> && ...) && (sizeof...(Views) > 0)
4884
  template<bool Const>
4885
  class zip_view<Views...>::iterator {
4886
  tuple<iterator_t<maybe-const<Const, Views>>...> current_; // exposition only
@@ -5247,11 +6100,11 @@ template<bool OtherConst>
5247
  iterator_t<maybe-const<OtherConst, Views>>> && ...)
5248
  friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
5249
  operator-(const sentinel& y, const iterator<OtherConst>& x);
5250
  ```
5251
 
5252
- *Effects:* Equivalent to `return -(x - y);`
5253
 
5254
  ### Zip transform view <a id="range.zip.transform">[[range.zip.transform]]</a>
5255
 
5256
  #### Overview <a id="range.zip.transform.overview">[[range.zip.transform.overview]]</a>
5257
 
@@ -5382,11 +6235,11 @@ namespace std::ranges {
5382
 
5383
  constexpr iterator(Parent& parent, ziperator<Const> inner); // exposition only
5384
 
5385
  public:
5386
  using iterator_category = see belownc; // not always present
5387
- using iterator_concept = typename ziperator<Const>::iterator_concept;
5388
  using value_type =
5389
  remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
5390
  range_reference_t<maybe-const<Const, Views>>...>>;
5391
  using difference_type = range_difference_t<Base>;
5392
 
@@ -5685,11 +6538,12 @@ resulting view is empty.
5685
  The name `views::adjacent<N>` denotes a range adaptor object
5686
  [[range.adaptor.object]]. Given a subexpression `E` and a constant
5687
  expression `N`, the expression `views::adjacent<N>(E)` is
5688
  expression-equivalent to
5689
 
5690
- - `((void)E, auto(views::empty<tuple<>>))` if `N` is equal to `0`,
 
5691
  - otherwise, `adjacent_view<views::all_t<decltype((E))>, N>(E)`.
5692
 
5693
  [*Example 1*:
5694
 
5695
  ``` cpp
@@ -5753,10 +6607,13 @@ namespace std::ranges {
5753
  }
5754
  }
5755
 
5756
  constexpr auto size() requires sized_range<V>;
5757
  constexpr auto size() const requires sized_range<const V>;
 
 
 
5758
  };
5759
  }
5760
  ```
5761
 
5762
  ``` cpp
@@ -5778,10 +6635,25 @@ using CT = common_type_t<ST, size_t>;
5778
  auto sz = static_cast<CT>(ranges::size(base_));
5779
  sz -= std::min<CT>(sz, N - 1);
5780
  return static_cast<ST>(sz);
5781
  ```
5782
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5783
  #### Class template `adjacent_view::iterator` <a id="range.adjacent.iterator">[[range.adjacent.iterator]]</a>
5784
 
5785
  ``` cpp
5786
  namespace std::ranges {
5787
  template<forward_range V, size_t N>
@@ -6174,13 +7046,14 @@ resulting view is empty.
6174
 
6175
  The name `views::adjacent_transform<N>` denotes a range adaptor object
6176
  [[range.adaptor.object]]. Given subexpressions `E` and `F` and a
6177
  constant expression `N`:
6178
 
6179
- - If `N` is equal to `0`, `views::adjacent_transform<N>(E, F)` is
6180
- expression-equivalent to `((void)E, views::zip_transform(F))`, except
6181
- that the evaluations of `E` and `F` are indeterminately sequenced.
 
6182
  - Otherwise, the expression `views::adjacent_transform<N>(E, F)` is
6183
  expression-equivalent to
6184
  `adjacent_transform_view<views::all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F)`.
6185
 
6186
  [*Example 1*:
@@ -6221,11 +7094,11 @@ namespace std::ranges {
6221
 
6222
  public:
6223
  adjacent_transform_view() = default;
6224
  constexpr explicit adjacent_transform_view(V base, F fun);
6225
 
6226
- constexpr V base() const & requires copy_constructible<InnerView> { return inner_.base(); }
6227
  constexpr V base() && { return std::move(inner_).base(); }
6228
 
6229
  constexpr auto begin() {
6230
  return iterator<false>(*this, inner_.begin());
6231
  }
@@ -6259,10 +7132,18 @@ namespace std::ranges {
6259
  }
6260
 
6261
  constexpr auto size() const requires sized_range<const InnerView> {
6262
  return inner_.size();
6263
  }
 
 
 
 
 
 
 
 
6264
  };
6265
  }
6266
  ```
6267
 
6268
  ``` cpp
@@ -6289,11 +7170,11 @@ namespace std::ranges {
6289
 
6290
  constexpr iterator(Parent& parent, inner-iterator<Const> inner); // exposition only
6291
 
6292
  public:
6293
  using iterator_category = see below;
6294
- using iterator_concept = typename inner-iterator<Const>::iterator_concept;
6295
  using value_type =
6296
  remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
6297
  REPEAT(range_reference_t<Base>, N)...>>;
6298
  using difference_type = range_difference_t<Base>;
6299
 
@@ -6563,11 +7444,11 @@ constexpr sentinel(sentinel<!Const> i)
6563
  template<bool OtherConst>
6564
  requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6565
  friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
6566
  ```
6567
 
6568
- *Effects:* Equivalent to `return x.`*`inner_`*` == y.`*`inner_`*`;`
6569
 
6570
  ``` cpp
6571
  template<bool OtherConst>
6572
  requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6573
  friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
@@ -6577,11 +7458,11 @@ template<bool OtherConst>
6577
  requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
6578
  friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
6579
  operator-(const sentinel& x, const iterator<OtherConst>& y);
6580
  ```
6581
 
6582
- *Effects:* Equivalent to `return x.`*`inner_`*` - y.`*`inner_`*`;`
6583
 
6584
  ### Chunk view <a id="range.chunk">[[range.chunk]]</a>
6585
 
6586
  #### Overview <a id="range.chunk.overview">[[range.chunk.overview]]</a>
6587
 
@@ -6650,10 +7531,13 @@ namespace std::ranges {
6650
  constexpr outer-iterator begin();
6651
  constexpr default_sentinel_t end() const noexcept;
6652
 
6653
  constexpr auto size() requires sized_range<V>;
6654
  constexpr auto size() const requires sized_range<const V>;
 
 
 
6655
  };
6656
 
6657
  template<class R>
6658
  chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;
6659
  }
@@ -6695,10 +7579,22 @@ constexpr auto size() const requires sized_range<const V>;
6695
 
6696
  ``` cpp
6697
  return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
6698
  ```
6699
 
 
 
 
 
 
 
 
 
 
 
 
 
6700
  #### Class `chunk_view::outer-iterator` <a id="range.chunk.outer.iter">[[range.chunk.outer.iter]]</a>
6701
 
6702
  ``` cpp
6703
  namespace std::ranges {
6704
  template<view V>
@@ -6814,10 +7710,12 @@ namespace std::ranges {
6814
  constexpr inner-iterator begin() const noexcept;
6815
  constexpr default_sentinel_t end() const noexcept;
6816
 
6817
  constexpr auto size() const
6818
  requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
 
 
6819
  };
6820
  }
6821
  ```
6822
 
6823
  ``` cpp
@@ -6848,10 +7746,20 @@ constexpr auto size() const
6848
  ``` cpp
6849
  return to-unsigned-like(ranges::min(parent_->remainder_,
6850
  ranges::end(parent_->base_) - *parent_->current_));
6851
  ```
6852
 
 
 
 
 
 
 
 
 
 
 
6853
  #### Class `chunk_view::inner-iterator` <a id="range.chunk.inner.iter">[[range.chunk.inner.iter]]</a>
6854
 
6855
  ``` cpp
6856
  namespace std::ranges {
6857
  template<view V>
@@ -7026,10 +7934,13 @@ namespace std::ranges {
7026
  }
7027
  }
7028
 
7029
  constexpr auto size() requires sized_range<V>;
7030
  constexpr auto size() const requires sized_range<const V>;
 
 
 
7031
  };
7032
  }
7033
  ```
7034
 
7035
  ``` cpp
@@ -7050,10 +7961,22 @@ constexpr auto size() const requires sized_range<const V>;
7050
 
7051
  ``` cpp
7052
  return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
7053
  ```
7054
 
 
 
 
 
 
 
 
 
 
 
 
 
7055
  #### Class template `chunk_view::iterator` for forward ranges <a id="range.chunk.fwd.iter">[[range.chunk.fwd.iter]]</a>
7056
 
7057
  ``` cpp
7058
  namespace std::ranges {
7059
  template<view V>
@@ -7426,10 +8349,13 @@ namespace std::ranges {
7426
  requires (!(simple-view<V> && slide-caches-nothing<const V>));
7427
  constexpr auto end() const requires slide-caches-nothing<const V>;
7428
 
7429
  constexpr auto size() requires sized_range<V>;
7430
  constexpr auto size() const requires sized_range<const V>;
 
 
 
7431
  };
7432
 
7433
  template<class R>
7434
  slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>;
7435
  }
@@ -7513,10 +8439,24 @@ constexpr auto size() const requires sized_range<const V>;
7513
  auto sz = ranges::distance(base_) - n_ + 1;
7514
  if (sz < 0) sz = 0;
7515
  return to-unsigned-like(sz);
7516
  ```
7517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7518
  #### Class template `slide_view::iterator` <a id="range.slide.iterator">[[range.slide.iterator]]</a>
7519
 
7520
  ``` cpp
7521
  namespace std::ranges {
7522
  template<forward_range V>
@@ -8180,10 +9120,13 @@ namespace std::ranges {
8180
  }
8181
  }
8182
 
8183
  constexpr auto size() requires sized_range<V>;
8184
  constexpr auto size() const requires sized_range<const V>;
 
 
 
8185
  };
8186
 
8187
  template<class R>
8188
  stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;
8189
  }
@@ -8213,10 +9156,22 @@ constexpr auto size() const requires sized_range<const V>;
8213
 
8214
  ``` cpp
8215
  return to-unsigned-like(div-ceil(ranges::distance(base_), stride_));
8216
  ```
8217
 
 
 
 
 
 
 
 
 
 
 
 
 
8218
  #### Class template `stride_view::iterator` <a id="range.stride.iterator">[[range.stride.iterator]]</a>
8219
 
8220
  ``` cpp
8221
  namespace std::ranges {
8222
  template<input_range V>
@@ -8374,11 +9329,11 @@ return *this;
8374
 
8375
  ``` cpp
8376
  constexpr void operator++(int);
8377
  ```
8378
 
8379
- *Effects:* Equivalent to: `++*this;`
8380
 
8381
  ``` cpp
8382
  constexpr iterator operator++(int) requires forward_range<Base>;
8383
  ```
8384
 
@@ -8616,11 +9571,11 @@ namespace std::ranges {
8616
  concept cartesian-product-is-bidirectional = // exposition only
8617
  (bidirectional_range<maybe-const<Const, First>> && ... &&
8618
  (bidirectional_range<maybe-const<Const, Vs>>
8619
  && cartesian-product-common-arg<maybe-const<Const, Vs>>));
8620
 
8621
- template<class First, class... Vs>
8622
  concept cartesian-product-is-common = // exposition only
8623
  cartesian-product-common-arg<First>;
8624
 
8625
  template<class... Vs>
8626
  concept cartesian-product-is-sized = // exposition only
@@ -9159,5 +10114,495 @@ ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
9159
  the following expressions:
9160
 
9161
  - `noexcept(ranges::iter_swap(std::get<`i`>(l.`*`current_`*`), std::get<`i`>(r.`*`current_`*`)))`
9162
  for every integer 0 ≤ i ≤ `sizeof...(Vs)`.
9163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  - Otherwise, `movable-box<T>` should store only a `T` if either `T`
158
  models `movable` or `is_nothrow_move_constructible_v<T>` is `true`.
159
 
160
  ### Non-propagating cache <a id="range.nonprop.cache">[[range.nonprop.cache]]</a>
161
 
162
+ Some types in [[range.adaptors]] are specified in terms of an
163
  exposition-only class template *`non-propagating-{}cache`*.
164
  `non-propagating-cache<T>` behaves exactly like `optional<T>` with the
165
  following differences:
166
 
167
  - `non-propagating-cache<T>` constrains its type parameter `T` with
 
236
 
237
  template<class T>
238
  constexpr T& as-lvalue(T&& t) { // exposition only
239
  return static_cast<T&>(t);
240
  }
241
+
242
+ template<bool Const, class... Views>
243
+ concept all-random-access = // exposition only
244
+ (random_access_range<maybe-const<Const, Views>> && ...);
245
+ template<bool Const, class... Views>
246
+ concept all-bidirectional = // exposition only
247
+ (bidirectional_range<maybe-const<Const, Views>> && ...);
248
+ template<bool Const, class... Views>
249
+ concept all-forward = // exposition only
250
+ (forward_range<maybe-const<Const, Views>> && ...);
251
  }
252
  ```
253
 
254
  ### All view <a id="range.all">[[range.all]]</a>
255
 
 
293
  { return ranges::empty(*r_); }
294
 
295
  constexpr auto size() const requires sized_range<R>
296
  { return ranges::size(*r_); }
297
 
298
+ constexpr auto reserve_hint() const requires approximately_sized_range<R>
299
+ { return ranges::reserve_hint(*r_); }
300
+
301
  constexpr auto data() const requires contiguous_range<R>
302
  { return ranges::data(*r_); }
303
  };
304
 
305
  template<class R>
 
369
  constexpr auto size() requires sized_range<R>
370
  { return ranges::size(r_); }
371
  constexpr auto size() const requires sized_range<const R>
372
  { return ranges::size(r_); }
373
 
374
+ constexpr auto reserve_hint() requires approximately_sized_range<R>
375
+ { return ranges::reserve_hint(r_); }
376
+ constexpr auto reserve_hint() const requires approximately_sized_range<const R>
377
+ { return ranges::reserve_hint(r_); }
378
+
379
  constexpr auto data() requires contiguous_range<R>
380
  { return ranges::data(r_); }
381
  constexpr auto data() const requires contiguous_range<const R>
382
  { return ranges::data(r_); }
383
  };
 
402
  The name `views::as_rvalue` denotes a range adaptor object
403
  [[range.adaptor.object]]. Let `E` be an expression and let `T` be
404
  `decltype((E))`. The expression `views::as_rvalue(E)` is
405
  expression-equivalent to:
406
 
407
+ - `views::all(E)` if `T` models `input_range` and
408
  `same_as<range_rvalue_reference_t<T>, range_reference_t<T>>` is
409
  `true`.
410
  - Otherwise, `as_rvalue_view(E)`.
411
 
412
  [*Example 1*:
 
456
  }
457
  }
458
 
459
  constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
460
  constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
461
+
462
+ constexpr auto reserve_hint() requires approximately_sized_range<V>
463
+ { return ranges::reserve_hint(base_); }
464
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>
465
+ { return ranges::reserve_hint(base_); }
466
  };
467
 
468
  template<class R>
469
  as_rvalue_view(R&&) -> as_rvalue_view<views::all_t<R>>;
470
  }
 
848
  regular_invocable<const F&, range_reference_t<const V>>;
849
 
850
  constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
851
  constexpr auto size() const requires sized_range<const V>
852
  { return ranges::size(base_); }
853
+
854
+ constexpr auto reserve_hint() requires approximately_sized_range<V>
855
+ { return ranges::reserve_hint(base_); }
856
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>
857
+ { return ranges::reserve_hint(base_); }
858
  };
859
 
860
  template<class R, class F>
861
  transform_view(R&&, F) -> transform_view<views::all_t<R>, F>;
862
  }
 
1436
 
1437
  constexpr auto size() const requires sized_range<const V> {
1438
  auto n = ranges::size(base_);
1439
  return ranges::min(n, static_cast<decltype(n)>(count_));
1440
  }
1441
+
1442
+ constexpr auto reserve_hint() {
1443
+ if constexpr (approximately_sized_range<V>) {
1444
+ auto n = static_cast<range_difference_t<V>>(ranges::reserve_hint(base_));
1445
+ return to-unsigned-like(ranges::min(n, count_));
1446
+ }
1447
+ return to-unsigned-like(count_);
1448
+ }
1449
+
1450
+ constexpr auto reserve_hint() const {
1451
+ if constexpr (approximately_sized_range<const V>) {
1452
+ auto n = static_cast<range_difference_t<const V>>(ranges::reserve_hint(base_));
1453
+ return to-unsigned-like(ranges::min(n, count_));
1454
+ }
1455
+ return to-unsigned-like(count_);
1456
+ }
1457
  };
1458
 
1459
  template<class R>
1460
  take_view(R&&, range_difference_t<R>)
1461
  -> take_view<views::all_t<R>>;
 
1705
  then
1706
  `U(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::end(E))`,
1707
  except that `E` is evaluated only once, where `U` is
1708
  `span<typename T::element_type>` if `T` is a specialization of `span`
1709
  and `T` otherwise.
1710
+ - Otherwise, if `T` is a specialization of `subrange` that models
1711
+ `random_access_range` and `sized_range`, then
1712
  `T(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::{}end(E),
1713
  to-unsigned-like(ranges::distance(E) -
1714
  std::min<D>(ranges::distance(E), F)))`, except that `E` and `F` are
1715
  each evaluated only once.
1716
  - Otherwise, if `T` is a specialization of `repeat_view`
 
1771
  const auto s = ranges::size(base_);
1772
  const auto c = static_cast<decltype(s)>(count_);
1773
  return s < c ? 0 : s - c;
1774
  }
1775
 
1776
+ constexpr auto reserve_hint() requires approximately_sized_range<V> {
1777
+ const auto s = static_cast<range_difference_t<V>>(ranges::reserve_hint(base_));
1778
+ return to-unsigned-like(s < count_ ? 0 : s - count_);
1779
+ }
1780
+
1781
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V> {
1782
+ const auto s = static_cast<range_difference_t<const V>>(ranges::reserve_hint(base_));
1783
+ return to-unsigned-like(s < count_ ? 0 : s - count_);
1784
+ }
1785
+
1786
  private:
1787
  V base_ = V(); // exposition only
1788
  range_difference_t<V> count_ = 0; // exposition only
1789
  };
1790
 
 
2287
  noexcept(noexcept(ranges::iter_swap(*x.inner_, *y.inner_)))
2288
  requires indirectly_swappable<InnerIter>;
2289
  ```
2290
 
2291
  *Effects:* Equivalent to:
2292
+ `ranges::iter_swap(*x.`*`inner_`*`, *y.`*`inner_`*`);`
2293
 
2294
  #### Class template `join_view::sentinel` <a id="range.join.sentinel">[[range.join.sentinel]]</a>
2295
 
2296
  ``` cpp
2297
  namespace std::ranges {
 
2366
 
2367
  #### Class template `join_with_view` <a id="range.join.with.view">[[range.join.with.view]]</a>
2368
 
2369
  ``` cpp
2370
  namespace std::ranges {
 
 
 
 
 
 
2371
  template<class R>
2372
  concept bidirectional-common = bidirectional_range<R> && common_range<R>; // exposition only
2373
 
2374
  template<input_range V, forward_range Pattern>
2375
  requires view<V> && input_range<range_reference_t<V>>
2376
  && view<Pattern>
2377
+ && concatable<range_reference_t<V>, Pattern>
2378
  class join_with_view : public view_interface<join_with_view<V, Pattern>> {
2379
  using InnerRng = range_reference_t<V>; // exposition only
2380
 
2381
  V base_ = V(); // exposition only
2382
  non-propagating-cache<iterator_t<V>> outer_it_; // exposition only, present only
 
2418
  }
2419
  constexpr auto begin() const
2420
  requires forward_range<const V> &&
2421
  forward_range<const Pattern> &&
2422
  is_reference_v<range_reference_t<const V>> &&
2423
+ input_range<range_reference_t<const V>> &&
2424
+ concatable<range_reference_t<const V>, const Pattern> {
2425
  return iterator<true>{*this, ranges::begin(base_)};
2426
  }
2427
 
2428
  constexpr auto end() {
2429
  if constexpr (forward_range<V> &&
 
2434
  return sentinel<simple-view<V> && simple-view<Pattern>>{*this};
2435
  }
2436
  constexpr auto end() const
2437
  requires forward_range<const V> && forward_range<const Pattern> &&
2438
  is_reference_v<range_reference_t<const V>> &&
2439
+ input_range<range_reference_t<const V>> &&
2440
+ concatable<range_reference_t<const V>, const Pattern> {
2441
  using InnerConstRng = range_reference_t<const V>;
2442
  if constexpr (forward_range<InnerConstRng> &&
2443
  common_range<const V> && common_range<InnerConstRng>)
2444
  return iterator<true>{*this, ranges::end(base_)};
2445
  else
 
2477
 
2478
  ``` cpp
2479
  namespace std::ranges {
2480
  template<input_range V, forward_range Pattern>
2481
  requires view<V> && input_range<range_reference_t<V>>
2482
+ && view<Pattern> && concatable<range_reference_t<V>, Pattern>
2483
  template<bool Const>
2484
  class join_with_view<V, Pattern>::iterator {
2485
  using Parent = maybe-const<Const, join_with_view>; // exposition only
2486
  using Base = maybe-const<Const, V>; // exposition only
2487
  using InnerBase = range_reference_t<Base>; // exposition only
 
2580
  iter_reference_t<PatternIter>>>
2581
  ```
2582
 
2583
  is `false`, `iterator_category` denotes `input_iterator_tag`.
2584
  - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
2585
+ `derived_from<bidirectional_iterator_tag>` and *`InnerBase`* and
2586
  *`PatternBase`* each model `common_range`, `iterator_category` denotes
2587
  `bidirectional_iterator_tag`.
2588
  - Otherwise, if *OUTERC*, *INNERC*, and *PATTERNC* each model
2589
  `derived_from<forward_iterator_tag>`, `iterator_category` denotes
2590
  `forward_iterator_tag`.
 
2648
  ``` cpp
2649
  while (true) {
2650
  if (inner_it_.index() == 0) {
2651
  if (std::get<0>(inner_it_) != ranges::end(parent_->pattern_))
2652
  break;
2653
+ inner_it_.template emplace<1>(ranges::begin(update-inner()));
2654
  } else {
2655
  if (std::get<1>(inner_it_) != ranges::end(get-inner()))
2656
  break;
2657
  if (++outer() == ranges::end(parent_->base_)) {
2658
  if constexpr (ref-is-glvalue)
2659
+ inner_it_.template emplace<0>();
2660
  break;
2661
  }
2662
+ inner_it_.template emplace<0>(ranges::begin(parent_->pattern_));
2663
  }
2664
  }
2665
  ```
2666
 
2667
  [*Note 1*: `join_with_view` iterators use the *satisfy* function to
 
2678
  first overload, also initializes *outer_it\_* with `std::move(outer)`.
2679
  Then, equivalent to:
2680
 
2681
  ``` cpp
2682
  if (outer() != ranges::end(parent_->base_)) {
2683
+ inner_it_.template emplace<1>(ranges::begin(update-inner()));
2684
  satisfy();
2685
  }
2686
  ```
2687
 
2688
  ``` cpp
 
2695
  *Effects:* Initializes *outer_it\_* with `std::move(i.`*`outer_it_`*`)`
2696
  and *parent\_* with `i.`*`parent_`*. Then, equivalent to:
2697
 
2698
  ``` cpp
2699
  if (i.inner_it_.index() == 0)
2700
+ inner_it_.template emplace<0>(std::get<0>(std::move(i.inner_it_)));
2701
  else
2702
+ inner_it_.template emplace<1>(std::get<1>(std::move(i.inner_it_)));
2703
  ```
2704
 
2705
  [*Note 2*: `Const` can only be `true` when *Base* models
2706
  `forward_range`. — *end note*]
2707
 
 
2757
  *Effects:* Equivalent to:
2758
 
2759
  ``` cpp
2760
  if (outer_it_ == ranges::end(parent_->base_)) {
2761
  auto&& inner = *--outer_it_;
2762
+ inner_it_.template emplace<1>(ranges::end(inner));
2763
  }
2764
 
2765
  while (true) {
2766
  if (inner_it_.index() == 0) {
2767
  auto& it = std::get<0>(inner_it_);
2768
  if (it == ranges::begin(parent_->pattern_)) {
2769
  auto&& inner = *--outer_it_;
2770
+ inner_it_.template emplace<1>(ranges::end(inner));
2771
  } else {
2772
  break;
2773
  }
2774
  } else {
2775
  auto& it = std::get<1>(inner_it_);
2776
  auto&& inner = *outer_it_;
2777
  if (it == ranges::begin(inner)) {
2778
+ inner_it_.template emplace<0>(ranges::end(parent_->pattern_));
2779
  } else {
2780
  break;
2781
  }
2782
  }
2783
  }
 
2815
 
2816
  ``` cpp
2817
  namespace std::ranges {
2818
  template<input_range V, forward_range Pattern>
2819
  requires view<V> && input_range<range_reference_t<V>>
2820
+ && view<Pattern> && concatable<range_reference_t<V>, Pattern>
2821
  template<bool Const>
2822
  class join_with_view<V, Pattern>::sentinel {
2823
  using Parent = maybe-const<Const, join_with_view>; // exposition only
2824
  using Base = maybe-const<Const, V>; // exposition only
2825
  sentinel_t<Base> end_ = sentinel_t<Base>(); // exposition only
 
3064
  ``` cpp
3065
  constexpr outer-iterator(outer-iterator<!Const> i)
3066
  requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
3067
  ```
3068
 
3069
+ *Effects:* Initializes *parent\_* with `i.`*`parent_`*, *current\_* with
3070
+ `std::move(i.`*`current_`*`)`, and *trailing_empty\_* with
3071
+ `i.`*`trailing_empty_`*.
3072
 
3073
  ``` cpp
3074
  constexpr value_type operator*() const;
3075
  ```
3076
 
 
3145
  struct lazy_split_view<V, Pattern>::outer-iterator<Const>::value_type
3146
  : view_interface<value_type> {
3147
  private:
3148
  outer-iterator i_ = outer-iterator(); // exposition only
3149
 
3150
+ constexpr explicit value_type(outer-iterator i); // exposition only
 
 
3151
 
3152
+ public:
3153
  constexpr inner-iterator<Const> begin() const;
3154
  constexpr default_sentinel_t end() const noexcept;
3155
  };
3156
  }
3157
  ```
 
3189
  using Base = maybe-const<Const, V>; // exposition only
3190
  outer-iterator<Const> i_ = outer-iterator<Const>(); // exposition only
3191
  bool incremented_ = false; // exposition only
3192
 
3193
  public:
3194
+ using iterator_concept = outer-iterator<Const>::iterator_concept;
3195
 
3196
  using iterator_category = see belownc; // present only if Base
3197
  // models forward_range
3198
  using value_type = range_value_t<Base>;
3199
  using difference_type = range_difference_t<Base>;
 
3484
 
3485
  ``` cpp
3486
  constexpr iterator_t<V> base() const;
3487
  ```
3488
 
3489
+ *Effects:* Equivalent to: `return `*`cur_`*`;`
3490
 
3491
  ``` cpp
3492
  constexpr value_type operator*() const;
3493
  ```
3494
 
3495
+ *Effects:* Equivalent to: `return {`*`cur_`*`, `*`next_`*`.begin()};`
3496
 
3497
  ``` cpp
3498
  constexpr iterator& operator++();
3499
  ```
3500
 
 
3569
  ```
3570
 
3571
  *Effects:* Equivalent to:
3572
  `return x.`*`cur_`*` == y.`*`end_`*` && !x.`*`trailing_empty_`*`;`
3573
 
3574
+ ### Concat view <a id="range.concat">[[range.concat]]</a>
3575
+
3576
+ #### Overview <a id="range.concat.overview">[[range.concat.overview]]</a>
3577
+
3578
+ `concat_view` presents a view that concatenates all the underlying
3579
+ ranges.
3580
+
3581
+ The name `views::concat` denotes a customization point object
3582
+ [[customization.point.object]]. Given a pack of subexpressions `Es...`,
3583
+ the expression `views::concat(Es...)` is expression-equivalent to
3584
+
3585
+ - `views::all(Es...)` if `Es` is a pack with only one element whose type
3586
+ models `input_range`,
3587
+ - otherwise, `concat_view(Es...)`.
3588
+
3589
+ [*Example 1*:
3590
+
3591
+ ``` cpp
3592
+ vector<int> v1{1, 2, 3}, v2{4, 5}, v3{};
3593
+ array a{6, 7, 8};
3594
+ auto s = views::single(9);
3595
+ for (auto&& i : views::concat(v1, v2, v3, a, s)) {
3596
+ print("{} ", i); // prints 1 2 3 4 5 6 7 8 9
3597
+ }
3598
+ ```
3599
+
3600
+ — *end example*]
3601
+
3602
+ #### Class template `concat_view` <a id="range.concat.view">[[range.concat.view]]</a>
3603
+
3604
+ ``` cpp
3605
+ namespace std::ranges {
3606
+ template<class... Rs>
3607
+ using concat-reference-t = common_reference_t<range_reference_t<Rs>...>; // exposition only
3608
+ template<class... Rs>
3609
+ using concat-value-t = common_type_t<range_value_t<Rs>...>; // exposition only
3610
+ template<class... Rs>
3611
+ using concat-rvalue-reference-t = // exposition only
3612
+ common_reference_t<range_rvalue_reference_t<Rs>...>;
3613
+
3614
+ template<class... Rs>
3615
+ concept concat-indirectly-readable = see below; // exposition only
3616
+ template<class... Rs>
3617
+ concept concatable = see below; // exposition only
3618
+ template<bool Const, class... Rs>
3619
+ concept concat-is-random-access = see below; // exposition only
3620
+ template<bool Const, class... Rs>
3621
+ concept concat-is-bidirectional = see below; // exposition only
3622
+
3623
+ template<input_range... Views>
3624
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
3625
+ concatable<Views...>
3626
+ class concat_view : public view_interface<concat_view<Views...>> {
3627
+
3628
+ tuple<Views...> views_; // exposition only
3629
+
3630
+ // [range.concat.iterator], class template concat_view::iterator
3631
+ template<bool> class iterator; // exposition only
3632
+
3633
+ public:
3634
+ constexpr concat_view() = default;
3635
+ constexpr explicit concat_view(Views... views);
3636
+
3637
+ constexpr iterator<false> begin() requires (!(simple-view<Views> && ...));
3638
+ constexpr iterator<true> begin() const
3639
+ requires (range<const Views> && ...) && concatable<const Views...>;
3640
+
3641
+ constexpr auto end() requires (!(simple-view<Views> && ...));
3642
+ constexpr auto end() const
3643
+ requires (range<const Views> && ...) && concatable<const Views...>;
3644
+
3645
+ constexpr auto size() requires (sized_range<Views> && ...);
3646
+ constexpr auto size() const requires (sized_range<const Views> && ...);
3647
+ };
3648
+
3649
+ template<class... R>
3650
+ concat_view(R&&...) -> concat_view<views::all_t<R>...>;
3651
+ }
3652
+ ```
3653
+
3654
+ ``` cpp
3655
+ template<class... Rs>
3656
+ concept concat-indirectly-readable = see below; // exposition only
3657
+ ```
3658
+
3659
+ The exposition-only `concat-indirectly-readable` concept is equivalent
3660
+ to:
3661
+
3662
+ ``` cpp
3663
+ template<class Ref, class RRef, class It>
3664
+ concept concat-indirectly-readable-impl = // exposition only
3665
+ requires (const It it) {
3666
+ { *it } -> convertible_to<Ref>;
3667
+ { ranges::iter_move(it) } -> convertible_to<RRef>;
3668
+ };
3669
+
3670
+ template<class... Rs>
3671
+ concept concat-indirectly-readable = // exposition only
3672
+ common_reference_with<concat-reference-t<Rs...>&&,
3673
+ concat-value-t<Rs...>&> &&
3674
+ common_reference_with<concat-reference-t<Rs...>&&,
3675
+ concat-rvalue-reference-t<Rs...>&&> &&
3676
+ common_reference_with<concat-rvalue-reference-t<Rs...>&&,
3677
+ concat-value-t<Rs...> const&> &&
3678
+ (concat-indirectly-readable-impl<concat-reference-t<Rs...>,
3679
+ concat-rvalue-reference-t<Rs...>,
3680
+ iterator_t<Rs>> && ...);
3681
+ ```
3682
+
3683
+ ``` cpp
3684
+ template<class... Rs>
3685
+ concept concatable = see below; // exposition only
3686
+ ```
3687
+
3688
+ The exposition-only `concatable` concept is equivalent to:
3689
+
3690
+ ``` cpp
3691
+ template<class... Rs>
3692
+ concept concatable = requires { // exposition only
3693
+ typename concat-reference-t<Rs...>;
3694
+ typename concat-value-t<Rs...>;
3695
+ typename concat-rvalue-reference-t<Rs...>;
3696
+ } && concat-indirectly-readable<Rs...>;
3697
+ ```
3698
+
3699
+ ``` cpp
3700
+ template<bool Const, class... Rs>
3701
+ concept concat-is-random-access = see below; // exposition only
3702
+ ```
3703
+
3704
+ Let `Fs` be the pack that consists of all elements of `Rs` except the
3705
+ last element, then *`concat-is-random-access`* is equivalent to:
3706
+
3707
+ ``` cpp
3708
+ template<bool Const, class... Rs>
3709
+ concept concat-is-random-access = // exposition only
3710
+ all-random-access<Const, Rs...> &&
3711
+ (common_range<maybe-const<Const, Fs>> && ...);
3712
+ ```
3713
+
3714
+ ``` cpp
3715
+ template<bool Const, class... Rs>
3716
+ concept concat-is-bidirectional = see below; // exposition only
3717
+ ```
3718
+
3719
+ Let `Fs` be the pack that consists of all elements of `Rs` except the
3720
+ last element, then *`concat-is-bidirectional`* is equivalent to:
3721
+
3722
+ ``` cpp
3723
+ template<bool Const, class... Rs>
3724
+ concept concat-is-bidirectional = // exposition only
3725
+ all-bidirectional<Const, Rs...> &&
3726
+ (common_range<maybe-const<Const, Fs>> && ...);
3727
+ ```
3728
+
3729
+ ``` cpp
3730
+ constexpr explicit concat_view(Views... views);
3731
+ ```
3732
+
3733
+ *Effects:* Initializes *views\_* with `std::move(views)...`.
3734
+
3735
+ ``` cpp
3736
+ constexpr iterator<false> begin() requires (!(simple-view<Views> && ...));
3737
+ constexpr iterator<true> begin() const
3738
+ requires (range<const Views> && ...) && concatable<const Views...>;
3739
+ ```
3740
+
3741
+ *Effects:* Let *is-const* be `true` for the const-qualified overload,
3742
+ and `false` otherwise. Equivalent to:
3743
+
3744
+ ``` cpp
3745
+ iterator<is-const> it(this, in_place_index<0>, ranges::begin(std::get<0>(views_)));
3746
+ it.template satisfy<0>();
3747
+ return it;
3748
+ ```
3749
+
3750
+ ``` cpp
3751
+ constexpr auto end() requires (!(simple-view<Views> && ...));
3752
+ constexpr auto end() const
3753
+ requires (range<const Views> && ...) && concatable<const Views...>;
3754
+ ```
3755
+
3756
+ *Effects:* Let *is-const* be `true` for the const-qualified overload,
3757
+ and `false` otherwise. Equivalent to:
3758
+
3759
+ ``` cpp
3760
+ constexpr auto N = sizeof...(Views);
3761
+ if constexpr (common_range<maybe-const<is-const, Views...[N - 1]>>) {
3762
+ return iterator<is-const>(this, in_place_index<N - 1>,
3763
+ ranges::end(std::get<N - 1>(views_)));
3764
+ } else {
3765
+ return default_sentinel;
3766
+ }
3767
+ ```
3768
+
3769
+ ``` cpp
3770
+ constexpr auto size() requires (sized_range<Views> && ...);
3771
+ constexpr auto size() const requires (sized_range<const Views> && ...);
3772
+ ```
3773
+
3774
+ *Effects:* Equivalent to:
3775
+
3776
+ ``` cpp
3777
+ return apply(
3778
+ [](auto... sizes) {
3779
+ using CT = make-unsigned-like-t<common_type_t<decltype(sizes)...>>;
3780
+ return (CT(sizes) + ...);
3781
+ },
3782
+ tuple-transform(ranges::size, views_));
3783
+ ```
3784
+
3785
+ #### Class `concat_view::iterator` <a id="range.concat.iterator">[[range.concat.iterator]]</a>
3786
+
3787
+ ``` cpp
3788
+ namespace std::ranges {
3789
+ template<input_range... Views>
3790
+ requires (view<Views> && ...) && (sizeof...(Views) > 0) &&
3791
+ concatable<Views...>
3792
+ template<bool Const>
3793
+ class concat_view<Views...>::iterator {
3794
+
3795
+ public:
3796
+ using iterator_category = see below; // not always present
3797
+ using iterator_concept = see below;
3798
+ using value_type = concat-value-t<maybe-const<Const, Views>...>;
3799
+ using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>;
3800
+
3801
+ private:
3802
+ using base-iter = // exposition only
3803
+ variant<iterator_t<maybe-const<Const, Views>>...>;
3804
+
3805
+ maybe-const<Const, concat_view>* parent_ = nullptr; // exposition only
3806
+ base-iter it_; // exposition only
3807
+
3808
+ template<size_t N>
3809
+ constexpr void satisfy(); // exposition only
3810
+ template<size_t N>
3811
+ constexpr void prev(); // exposition only
3812
+
3813
+ template<size_t N>
3814
+ constexpr void advance-fwd(difference_type offset, // exposition only
3815
+ difference_type steps);
3816
+ template<size_t N>
3817
+ constexpr void advance-bwd(difference_type offset, // exposition only
3818
+ difference_type steps);
3819
+
3820
+ template<class... Args>
3821
+ constexpr explicit iterator(maybe-const<Const, concat_view>* parent, // exposition only
3822
+ Args&&... args)
3823
+ requires constructible_from<base-iter, Args&&...>;
3824
+
3825
+ public:
3826
+ iterator() = default;
3827
+
3828
+ constexpr iterator(iterator<!Const> i)
3829
+ requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
3830
+
3831
+ constexpr decltype(auto) operator*() const;
3832
+ constexpr iterator& operator++();
3833
+ constexpr void operator++(int);
3834
+ constexpr iterator operator++(int)
3835
+ requires all-forward<Const, Views...>;
3836
+ constexpr iterator& operator--()
3837
+ requires concat-is-bidirectional<Const, Views...>;
3838
+ constexpr iterator operator--(int)
3839
+ requires concat-is-bidirectional<Const, Views...>;
3840
+ constexpr iterator& operator+=(difference_type n)
3841
+ requires concat-is-random-access<Const, Views...>;
3842
+ constexpr iterator& operator-=(difference_type n)
3843
+ requires concat-is-random-access<Const, Views...>;
3844
+ constexpr decltype(auto) operator[](difference_type n) const
3845
+ requires concat-is-random-access<Const, Views...>;
3846
+
3847
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
3848
+ requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
3849
+ friend constexpr bool operator==(const iterator& it, default_sentinel_t);
3850
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
3851
+ requires all-random-access<Const, Views...>;
3852
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
3853
+ requires all-random-access<Const, Views...>;
3854
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
3855
+ requires all-random-access<Const, Views...>;
3856
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
3857
+ requires all-random-access<Const, Views...>;
3858
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
3859
+ requires (all-random-access<Const, Views...> &&
3860
+ (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...));
3861
+ friend constexpr iterator operator+(const iterator& it, difference_type n)
3862
+ requires concat-is-random-access<Const, Views...>;
3863
+ friend constexpr iterator operator+(difference_type n, const iterator& it)
3864
+ requires concat-is-random-access<Const, Views...>;
3865
+ friend constexpr iterator operator-(const iterator& it, difference_type n)
3866
+ requires concat-is-random-access<Const, Views...>;
3867
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
3868
+ requires concat-is-random-access<Const, Views...>;
3869
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)
3870
+ requires see below;
3871
+ friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)
3872
+ requires see below;
3873
+ friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
3874
+ friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)
3875
+ requires see below;
3876
+ };
3877
+ }
3878
+ ```
3879
+
3880
+ `iterator::iterator_concept` is defined as follows:
3881
+
3882
+ - If `concat-is-random-access<Const, Views...>` is modeled, then
3883
+ `iterator_concept` denotes `random_access_iterator_tag`.
3884
+ - Otherwise, if `concat-is-bidirectional<Const, Views...>` is modeled,
3885
+ then `iterator_concept` denotes `bidirectional_iterator_tag`.
3886
+ - Otherwise, if `all-forward<Const, Views...>` is modeled, then
3887
+ `iterator_concept` denotes `forward_iterator_tag`.
3888
+ - Otherwise, `iterator_concept` denotes `input_iterator_tag`.
3889
+
3890
+ The member *typedef-name* `iterator_category` is defined if and only if
3891
+ `all-forward<Const, Views...>` is modeled. In that case,
3892
+ `iterator::iterator_category` is defined as follows:
3893
+
3894
+ - If `is_reference_v<concat-reference-t<maybe-const<Const, Views>...>>`
3895
+ is `false`, then `iterator_category` denotes `input_iterator_tag`.
3896
+ - Otherwise, let `Cs` denote the pack of types
3897
+ `iterator_traits<iterator_t<maybe-const<Const, Views>>>::iterator_category...`.
3898
+ - If
3899
+ `(derived_from<Cs, random_access_iterator_tag> && ...) && concat-is-random-ac-{cess}<Const, Views...>`
3900
+ is `true`, `iterator_category` denotes `random_access_iterator_tag`.
3901
+ - Otherwise, if
3902
+ `(derived_from<Cs, bidirectional_iterator_tag> && ...) && concat-is-{bidirectional}<Const, Views...>`
3903
+ is `true`, `iterator_category` denotes `bidirectional_iterator_tag`.
3904
+ - Otherwise, if `(derived_from<Cs, forward_iterator_tag> && ...)` is
3905
+ `true`, `iterator_category` denotes `forward_iterator_tag`.
3906
+ - Otherwise, `iterator_category` denotes `input_iterator_tag`.
3907
+
3908
+ ``` cpp
3909
+ template<size_t N>
3910
+ constexpr void satisfy();
3911
+ ```
3912
+
3913
+ *Effects:* Equivalent to:
3914
+
3915
+ ``` cpp
3916
+ if constexpr (N < (sizeof...(Views) - 1)) {
3917
+ if (std::get<N>(it_) == ranges::end(std::get<N>(parent_->views_))) {
3918
+ it_.template emplace<N + 1>(ranges::begin(std::get<N + 1>(parent_->views_)));
3919
+ satisfy<N + 1>();
3920
+ }
3921
+ }
3922
+ ```
3923
+
3924
+ ``` cpp
3925
+ template<size_t N>
3926
+ constexpr void prev();
3927
+ ```
3928
+
3929
+ *Effects:* Equivalent to:
3930
+
3931
+ ``` cpp
3932
+ if constexpr (N == 0) {
3933
+ --std::get<0>(it_);
3934
+ } else {
3935
+ if (std::get<N>(it_) == ranges::begin(std::get<N>(parent_->views_))) {
3936
+ it_.template emplace<N - 1>(ranges::end(std::get<N - 1>(parent_->views_)));
3937
+ prev<N - 1>();
3938
+ } else {
3939
+ --std::get<N>(it_);
3940
+ }
3941
+ }
3942
+ ```
3943
+
3944
+ ``` cpp
3945
+ template<size_t N>
3946
+ constexpr void advance-fwd(difference_type offset, difference_type steps);
3947
+ ```
3948
+
3949
+ *Effects:* Equivalent to:
3950
+
3951
+ ``` cpp
3952
+ using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;
3953
+ if constexpr (N == sizeof...(Views) - 1) {
3954
+ std::get<N>(it_) += static_cast<underlying_diff_type>(steps);
3955
+ } else {
3956
+ auto n_size = ranges::distance(std::get<N>(parent_->views_));
3957
+ if (offset + steps < n_size) {
3958
+ std::get<N>(it_) += static_cast<underlying_diff_type>(steps);
3959
+ } else {
3960
+ it_.template emplace<N + 1>(ranges::begin(std::get<N + 1>(parent_->views_)));
3961
+ advance-fwd<N + 1>(0, offset + steps - n_size);
3962
+ }
3963
+ }
3964
+ ```
3965
+
3966
+ ``` cpp
3967
+ template<size_t N>
3968
+ constexpr void advance-bwd(difference_type offset, difference_type steps);
3969
+ ```
3970
+
3971
+ *Effects:* Equivalent to:
3972
+
3973
+ ``` cpp
3974
+ using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;
3975
+ if constexpr (N == 0) {
3976
+ std::get<N>(it_) -= static_cast<underlying_diff_type>(steps);
3977
+ } else {
3978
+ if (offset >= steps) {
3979
+ std::get<N>(it_) -= static_cast<underlying_diff_type>(steps);
3980
+ } else {
3981
+ auto prev_size = ranges::distance(std::get<N - 1>(parent_->views_));
3982
+ it_.template emplace<N - 1>(ranges::end(std::get<N - 1>(parent_->views_)));
3983
+ advance-bwd<N - 1>(prev_size, steps - offset);
3984
+ }
3985
+ }
3986
+ ```
3987
+
3988
+ ``` cpp
3989
+ template<class... Args>
3990
+ constexpr explicit iterator(maybe-const<Const, concat_view>* parent,
3991
+ Args&&... args)
3992
+ requires constructible_from<base-iter, Args&&...>;
3993
+ ```
3994
+
3995
+ *Effects:* Initializes *parent\_* with `parent`, and initializes *it\_*
3996
+ with `std::forward<Args>(args)...`.
3997
+
3998
+ ``` cpp
3999
+ constexpr iterator(iterator<!Const> it)
4000
+ requires Const &&
4001
+ (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...);
4002
+ ```
4003
+
4004
+ *Preconditions:* `it.`*`it_`*`.valueless_by_exception()` is `false`.
4005
+
4006
+ *Effects:* Initializes *parent\_* with `it.`*`parent_`*, and let i be
4007
+ `it.`*`it_`*`.index()`, initializes *it\_* with
4008
+ *`base-iter`*`(in_place_index<`i`>, std::get<`i`>(std::move(it.`*`it_`*`)))`.
4009
+
4010
+ ``` cpp
4011
+ constexpr decltype(auto) operator*() const;
4012
+ ```
4013
+
4014
+ *Preconditions:* *`it_`*`.valueless_by_exception()` is `false`.
4015
+
4016
+ *Effects:* Equivalent to:
4017
+
4018
+ ``` cpp
4019
+ using reference = concat-reference-t<maybe-const<Const, Views>...>;
4020
+ return std::visit([](auto&& it) -> reference { return *it; },
4021
+ it_);
4022
+ ```
4023
+
4024
+ ``` cpp
4025
+ constexpr iterator& operator++();
4026
+ ```
4027
+
4028
+ *Preconditions:* *`it_`*`.valueless_by_exception()` is `false`.
4029
+
4030
+ *Effects:* Let i be *`it_`*`.index()`. Equivalent to:
4031
+
4032
+ ``` cpp
4033
+ ++std::get<i>(it_);
4034
+ satisfy<i>();
4035
+ return *this;
4036
+ ```
4037
+
4038
+ ``` cpp
4039
+ constexpr void operator++(int);
4040
+ ```
4041
+
4042
+ *Effects:* Equivalent to:
4043
+
4044
+ ``` cpp
4045
+ ++*this;
4046
+ ```
4047
+
4048
+ ``` cpp
4049
+ constexpr iterator operator++(int)
4050
+ requires all-forward<Const, Views...>;
4051
+ ```
4052
+
4053
+ *Effects:* Equivalent to:
4054
+
4055
+ ``` cpp
4056
+ auto tmp = *this;
4057
+ ++*this;
4058
+ return tmp;
4059
+ ```
4060
+
4061
+ ``` cpp
4062
+ constexpr iterator& operator--()
4063
+ requires concat-is-bidirectional<Const, Views...>;
4064
+ ```
4065
+
4066
+ *Preconditions:* *`it_`*`.valueless_by_exception()` is `false`.
4067
+
4068
+ *Effects:* Let i be *`it_`*`.index()`. Equivalent to:
4069
+
4070
+ ``` cpp
4071
+ prev<i>();
4072
+ return *this;
4073
+ ```
4074
+
4075
+ ``` cpp
4076
+ constexpr iterator operator--(int)
4077
+ requires concat-is-bidirectional<Const, Views...>;
4078
+ ```
4079
+
4080
+ *Effects:* Equivalent to:
4081
+
4082
+ ``` cpp
4083
+ auto tmp = *this;
4084
+ --*this;
4085
+ return tmp;
4086
+ ```
4087
+
4088
+ ``` cpp
4089
+ constexpr iterator& operator+=(difference_type n)
4090
+ requires concat-is-random-access<Const, Views...>;
4091
+ ```
4092
+
4093
+ *Preconditions:* *`it_`*`.valueless_by_exception()` is `false`.
4094
+
4095
+ *Effects:* Let i be *`it_`*`.index()`. Equivalent to:
4096
+
4097
+ ``` cpp
4098
+ if (n > 0) {
4099
+ advance-fwd<i>(std::get<i>(it_) - ranges::begin(std::get<i>(parent_->views_)), n);
4100
+ } else if (n < 0) {
4101
+ advance-bwd<i>(std::get<i>(it_) - ranges::begin(std::get<i>(parent_->views_)), -n);
4102
+ }
4103
+ return *this;
4104
+ ```
4105
+
4106
+ ``` cpp
4107
+ constexpr iterator& operator-=(difference_type n)
4108
+ requires concat-is-random-access<Const, Views...>;
4109
+ ```
4110
+
4111
+ *Effects:* Equivalent to:
4112
+
4113
+ ``` cpp
4114
+ *this += -n;
4115
+ return *this;
4116
+ ```
4117
+
4118
+ ``` cpp
4119
+ constexpr decltype(auto) operator[](difference_type n) const
4120
+ requires concat-is-random-access<Const, Views...>;
4121
+ ```
4122
+
4123
+ *Effects:* Equivalent to:
4124
+
4125
+ ``` cpp
4126
+ return *((*this) + n);
4127
+ ```
4128
+
4129
+ ``` cpp
4130
+ friend constexpr bool operator==(const iterator& x, const iterator& y)
4131
+ requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...);
4132
+ ```
4133
+
4134
+ *Preconditions:* `x.`*`it_`*`.valueless_by_exception()` and
4135
+ `y.`*`it_`*`.valueless_by_exception()` are each `false`.
4136
+
4137
+ *Effects:* Equivalent to:
4138
+
4139
+ ``` cpp
4140
+ return x.it_ == y.it_;
4141
+ ```
4142
+
4143
+ ``` cpp
4144
+ friend constexpr bool operator==(const iterator& it, default_sentinel_t);
4145
+ ```
4146
+
4147
+ *Preconditions:* `it.`*`it_`*`.valueless_by_exception()` is `false`.
4148
+
4149
+ *Effects:* Equivalent to:
4150
+
4151
+ ``` cpp
4152
+ constexpr auto last_idx = sizeof...(Views) - 1;
4153
+ return it.it_.index() == last_idx &&
4154
+ std::get<last_idx>(it.it_) == ranges::end(std::get<last_idx>(it.parent_->views_));
4155
+ ```
4156
+
4157
+ ``` cpp
4158
+ friend constexpr bool operator<(const iterator& x, const iterator& y)
4159
+ requires all-random-access<Const, Views...>;
4160
+ friend constexpr bool operator>(const iterator& x, const iterator& y)
4161
+ requires all-random-access<Const, Views...>;
4162
+ friend constexpr bool operator<=(const iterator& x, const iterator& y)
4163
+ requires all-random-access<Const, Views...>;
4164
+ friend constexpr bool operator>=(const iterator& x, const iterator& y)
4165
+ requires all-random-access<Const, Views...>;
4166
+ friend constexpr auto operator<=>(const iterator& x, const iterator& y)
4167
+ requires (all-random-access<Const, Views...> &&
4168
+ (three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...));
4169
+ ```
4170
+
4171
+ *Preconditions:* `x.`*`it_`*`.valueless_by_exception()` and
4172
+ `y.`*`it_`*`.valueless_by_exception()` are each `false`.
4173
+
4174
+ Let op be the operator.
4175
+
4176
+ *Effects:* Equivalent to:
4177
+
4178
+ ``` cpp
4179
+ return x.it_ op y.it_;
4180
+ ```
4181
+
4182
+ ``` cpp
4183
+ friend constexpr iterator operator+(const iterator& it, difference_type n)
4184
+ requires concat-is-random-access<Const, Views...>;
4185
+ ```
4186
+
4187
+ *Effects:* Equivalent to:
4188
+
4189
+ ``` cpp
4190
+ auto temp = it;
4191
+ temp += n;
4192
+ return temp;
4193
+ ```
4194
+
4195
+ ``` cpp
4196
+ friend constexpr iterator operator+(difference_type n, const iterator& it)
4197
+ requires concat-is-random-access<Const, Views...>;
4198
+ ```
4199
+
4200
+ *Effects:* Equivalent to:
4201
+
4202
+ ``` cpp
4203
+ return it + n;
4204
+ ```
4205
+
4206
+ ``` cpp
4207
+ friend constexpr iterator operator-(const iterator& it, difference_type n)
4208
+ requires concat-is-random-access<Const, Views...>;
4209
+ ```
4210
+
4211
+ *Effects:* Equivalent to:
4212
+
4213
+ ``` cpp
4214
+ auto temp = it;
4215
+ temp -= n;
4216
+ return temp;
4217
+ ```
4218
+
4219
+ ``` cpp
4220
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y)
4221
+ requires concat-is-random-access<Const, Views...>;
4222
+ ```
4223
+
4224
+ *Preconditions:* `x.`*`it_`*`.valueless_by_exception()` and
4225
+ `y.`*`it_`*`.valueless_by_exception()` are each `false`.
4226
+
4227
+ *Effects:* Let i_`x` denote `x.`*`it_`*`.index()` and i_`y` denote
4228
+ `y.`*`it_`*`.index()`.
4229
+
4230
+ - If i_`x`` > `i_`y`, let d_`y` be
4231
+ `ranges::distance(std::get<`i_`y``>(y.`*`it_`*`), ranges::end(std::get<`i_`y``>(y.`*`parent_`*`->`*`views_`*`)))`,
4232
+ d_`x` be
4233
+ `ranges::distance(ranges::begin(std::get<`i_`x``>(x.`*`parent_`*`->`*`views_`*`)), std::get<`i_`x``>(x.`*`it_`*`))`.
4234
+ Let s denote the sum of the sizes of all the ranges
4235
+ `std::get<`i`>(x.`*`parent_`*`->`*`views_`*`)` for every integer i in
4236
+ the range \[i_`y`` + 1`, i_`x`) if there is any, and `0` otherwise, of
4237
+ type `difference_type`, equivalent to:
4238
+ ``` cpp
4239
+ return $d_y$ + s + $d_x$;
4240
+ ```
4241
+ - otherwise, if i_`x`` < `i_`y` is `true`, equivalent to:
4242
+ ``` cpp
4243
+ return -(y - x);
4244
+ ```
4245
+ - otherwise, equivalent to:
4246
+ ``` cpp
4247
+ return std::get<$i_x$>(x.it_) - std::get<$i_y$>(y.it_);
4248
+ ```
4249
+
4250
+ ``` cpp
4251
+ friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)
4252
+ requires see below;
4253
+ ```
4254
+
4255
+ *Preconditions:* `x.`*`it_`*`.valueless_by_exception()` is `false`.
4256
+
4257
+ *Effects:* Let i_`x` denote `x.`*`it_`*`.index()`, d_`x` be
4258
+ `ranges::distance(std::get<`i_`x``>(x.`*`it_`*`), ranges::end(std::get<`i_`x``>(x.`*`parent_`*`->`*`views_`*`)))`.
4259
+ Let s denote the sum of the sizes of all the ranges
4260
+ `std::get<`i`>(x.`*`parent_`*`->`*`views_`*`)` for every integer i in
4261
+ the range \[i_`x`` + 1`, `sizeof...(Views)`) if there is any, and `0`
4262
+ otherwise, of type difference_type, equivalent to:
4263
+
4264
+ ``` cpp
4265
+ return -($d_x$ + s);
4266
+ ```
4267
+
4268
+ *Remarks:* Let `Fs` be the pack that consists of all elements of `Views`
4269
+ except the first element, the expression in the *requires-clause* is
4270
+ equivalent to:
4271
+
4272
+ ``` cpp
4273
+ (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
4274
+ iterator_t<maybe-const<Const, Views>>> && ...) &&
4275
+ (sized_range<maybe-const<Const, Fs>> && ...)
4276
+ ```
4277
+
4278
+ ``` cpp
4279
+ friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)
4280
+ requires see below;
4281
+ ```
4282
+
4283
+ *Effects:* Equivalent to:
4284
+
4285
+ ``` cpp
4286
+ return -(x - default_sentinel);
4287
+ ```
4288
+
4289
+ *Remarks:* Let `Fs` be the pack that consists of all elements of `Views`
4290
+ except the first element, the expression in the *requires-clause* is
4291
+ equivalent to:
4292
+
4293
+ ``` cpp
4294
+ (sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>,
4295
+ iterator_t<maybe-const<Const, Views>>> && ...) &&
4296
+ (sized_range<maybe-const<Const, Fs>> && ...)
4297
+ ```
4298
+
4299
+ ``` cpp
4300
+ friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);
4301
+ ```
4302
+
4303
+ *Preconditions:* `it.`*`it_`*`.valueless_by_exception()` is `false`.
4304
+
4305
+ *Effects:* Equivalent to:
4306
+
4307
+ ``` cpp
4308
+ return std::visit([](const auto& i)
4309
+ -> concat-rvalue-reference-t<maybe-const<Const, Views>...> {
4310
+ return ranges::iter_move(i);
4311
+ },
4312
+ it.it_);
4313
+ ```
4314
+
4315
+ *Remarks:* The exception specification is equivalent to:
4316
+
4317
+ ``` cpp
4318
+ ((is_nothrow_invocable_v<decltype(ranges::iter_move),
4319
+ const iterator_t<maybe-const<Const, Views>>&> &&
4320
+ is_nothrow_convertible_v<range_rvalue_reference_t<maybe-const<Const, Views>>,
4321
+ concat-rvalue-reference-t<maybe-const<Const, Views>...>>) &&
4322
+ ...)
4323
+ ```
4324
+
4325
+ ``` cpp
4326
+ friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)
4327
+ requires see below;
4328
+ ```
4329
+
4330
+ *Preconditions:* `x.`*`it_`*`.valueless_by_exception()` and
4331
+ `y.`*`it_`*`.valueless_by_exception()` are each `false`.
4332
+
4333
+ *Effects:* Equivalent to:
4334
+
4335
+ ``` cpp
4336
+ std::visit([&](const auto& it1, const auto& it2) {
4337
+ if constexpr (is_same_v<decltype(it1), decltype(it2)>) {
4338
+ ranges::iter_swap(it1, it2);
4339
+ } else {
4340
+ ranges::swap(*x, *y);
4341
+ }
4342
+ },
4343
+ x.it_, y.it_);
4344
+ ```
4345
+
4346
+ *Remarks:* The exception specification is equivalent to
4347
+
4348
+ ``` cpp
4349
+ (noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its)))
4350
+ ```
4351
+
4352
+ where `its` is a pack of lvalues of type
4353
+ `const iterator_t<`*`maybe-const`*`<Const, Views>>` respectively.
4354
+
4355
+ The expression in the *requires-clause* is equivalent to
4356
+
4357
+ ``` cpp
4358
+ swappable_with<iter_reference_t<iterator>, iter_reference_t<iterator>> &&
4359
+ (... && indirectly_swappable<iterator_t<maybe-const<Const, Views>>>)
4360
+ ```
4361
+
4362
  ### Counted view <a id="range.counted">[[range.counted]]</a>
4363
 
4364
  A counted view presents a view of the elements of the counted range
4365
  [[iterator.requirements.general]] `i`+\[0, `n`) for an iterator `i` and
4366
  non-negative integer `n`.
 
4437
  constexpr explicit common_view(V r);
4438
 
4439
  constexpr V base() const & requires copy_constructible<V> { return base_; }
4440
  constexpr V base() && { return std::move(base_); }
4441
 
4442
+ constexpr auto begin() requires (!simple-view<V>) {
4443
  if constexpr (random_access_range<V> && sized_range<V>)
4444
  return ranges::begin(base_);
4445
  else
4446
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
4447
  }
 
4451
  return ranges::begin(base_);
4452
  else
4453
  return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
4454
  }
4455
 
4456
+ constexpr auto end() requires (!simple-view<V>) {
4457
  if constexpr (random_access_range<V> && sized_range<V>)
4458
  return ranges::begin(base_) + ranges::distance(base_);
4459
  else
4460
  return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
4461
  }
 
4471
  return ranges::size(base_);
4472
  }
4473
  constexpr auto size() const requires sized_range<const V> {
4474
  return ranges::size(base_);
4475
  }
4476
+
4477
+ constexpr auto reserve_hint() requires approximately_sized_range<V> {
4478
+ return ranges::reserve_hint(base_);
4479
+ }
4480
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V> {
4481
+ return ranges::reserve_hint(base_);
4482
+ }
4483
  };
4484
 
4485
  template<class R>
4486
  common_view(R&&) -> common_view<views::all_t<R>>;
4487
  }
 
4503
  The name `views::reverse` denotes a range adaptor object
4504
  [[range.adaptor.object]]. Given a subexpression `E`, the expression
4505
  `views::reverse(E)` is expression-equivalent to:
4506
 
4507
  - If the type of `E` is a (possibly cv-qualified) specialization of
4508
+ `reverse_view`, then `E.base()`.
4509
  - Otherwise, if the type of `E` is cv
4510
  `subrange<reverse_iterator<I>, reverse_iterator<I>, K>` for some
4511
  iterator type `I` and value `K` of type `subrange_kind`,
4512
+ - if `K` is `subrange_kind::sized`, then
4513
+ `subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())`;
4514
+ - otherwise, `subrange<I, I, K>(E.end().base(), E.begin().base())`.
 
 
 
 
 
4515
 
4516
  However, in either case `E` is evaluated only once.
4517
+ - Otherwise, `reverse_view{E}`.
4518
 
4519
  [*Example 1*:
4520
 
4521
  ``` cpp
4522
  vector<int> is {0,1,2,3,4};
 
4556
  }
4557
 
4558
  constexpr auto size() const requires sized_range<const V> {
4559
  return ranges::size(base_);
4560
  }
4561
+
4562
+ constexpr auto reserve_hint() requires approximately_sized_range<V> {
4563
+ return ranges::reserve_hint(base_);
4564
+ }
4565
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V> {
4566
+ return ranges::reserve_hint(base_);
4567
+ }
4568
  };
4569
 
4570
  template<class R>
4571
  reverse_view(R&&) -> reverse_view<views::all_t<R>>;
4572
  }
 
4667
  constexpr auto end() requires (!simple-view<V>) { return ranges::cend(base_); }
4668
  constexpr auto end() const requires range<const V> { return ranges::cend(base_); }
4669
 
4670
  constexpr auto size() requires sized_range<V> { return ranges::size(base_); }
4671
  constexpr auto size() const requires sized_range<const V> { return ranges::size(base_); }
4672
+
4673
+ constexpr auto reserve_hint() requires approximately_sized_range<V>
4674
+ { return ranges::reserve_hint(base_); }
4675
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>
4676
+ { return ranges::reserve_hint(base_); }
4677
  };
4678
 
4679
  template<class R>
4680
  as_const_view(R&&) -> as_const_view<views::all_t<R>>;
4681
  }
 
4796
  { return ranges::size(base_); }
4797
 
4798
  constexpr auto size() const requires sized_range<const V>
4799
  { return ranges::size(base_); }
4800
 
4801
+ constexpr auto reserve_hint() requires approximately_sized_range<V>
4802
+ { return ranges::reserve_hint(base_); }
4803
+
4804
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>
4805
+ { return ranges::reserve_hint(base_); }
4806
+
4807
  private:
4808
  // [range.elements.iterator], class template elements_view::iterator
4809
  template<bool> class iterator; // exposition only
4810
 
4811
  // [range.elements.sentinel], class template elements_view::sentinel
 
5194
  #### Overview <a id="range.enumerate.overview">[[range.enumerate.overview]]</a>
5195
 
5196
  `enumerate_view` is a view whose elements represent both the position
5197
  and value from a sequence of elements.
5198
 
5199
+ The name `views::enumerate` denotes a range adaptor object
5200
+ [[range.adaptor.object]]. Given a subexpression `E`, the expression
5201
+ `views::enumerate(E)` is expression-equivalent to
5202
  `enumerate_view<views::all_t<decltype((E))>>(E)`.
5203
 
5204
  [*Example 1*:
5205
 
5206
  ``` cpp
 
5236
  { return iterator<false>(ranges::begin(base_), 0); }
5237
  constexpr auto begin() const requires range-with-movable-references<const V>
5238
  { return iterator<true>(ranges::begin(base_), 0); }
5239
 
5240
  constexpr auto end() requires (!simple-view<V>) {
5241
+ if constexpr (forward_range<V> && common_range<V> && sized_range<V>)
5242
  return iterator<false>(ranges::end(base_), ranges::distance(base_));
5243
  else
5244
  return sentinel<false>(ranges::end(base_));
5245
  }
5246
  constexpr auto end() const requires range-with-movable-references<const V> {
5247
+ if constexpr (forward_range<const V> && common_range<const V> && sized_range<const V>)
5248
  return iterator<true>(ranges::end(base_), ranges::distance(base_));
5249
  else
5250
  return sentinel<true>(ranges::end(base_));
5251
  }
5252
 
5253
  constexpr auto size() requires sized_range<V>
5254
  { return ranges::size(base_); }
5255
  constexpr auto size() const requires sized_range<const V>
5256
  { return ranges::size(base_); }
5257
 
5258
+ constexpr auto reserve_hint() requires approximately_sized_range<V>
5259
+ { return ranges::reserve_hint(base_); }
5260
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>
5261
+ { return ranges::reserve_hint(base_); }
5262
+
5263
  constexpr V base() const & requires copy_constructible<V> { return base_; }
5264
  constexpr V base() && { return std::move(base_); }
5265
  };
5266
 
5267
  template<class R>
 
5337
  requires random_access_range<Base>;
5338
  friend constexpr iterator operator+(difference_type x, const iterator& y)
5339
  requires random_access_range<Base>;
5340
  friend constexpr iterator operator-(const iterator& x, difference_type y)
5341
  requires random_access_range<Base>;
5342
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept;
5343
 
5344
  friend constexpr auto iter_move(const iterator& i)
5345
  noexcept(noexcept(ranges::iter_move(i.current_)) &&
5346
  is_nothrow_move_constructible_v<range_rvalue_reference_t<Base>>) {
5347
  return tuple<difference_type,
 
5519
  temp -= y;
5520
  return temp;
5521
  ```
5522
 
5523
  ``` cpp
5524
+ friend constexpr difference_type operator-(const iterator& x, const iterator& y) noexcept;
5525
  ```
5526
 
5527
  *Effects:* Equivalent to: `return x.`*`pos_`*` - y.`*`pos_`*`;`
5528
 
5529
  #### Class template `enumerate_view::sentinel` <a id="range.enumerate.sentinel">[[range.enumerate.sentinel]]</a>
 
5730
 
5731
  #### Class template `zip_view::iterator` <a id="range.zip.iterator">[[range.zip.iterator]]</a>
5732
 
5733
  ``` cpp
5734
  namespace std::ranges {
 
 
 
 
 
 
 
 
 
 
5735
  template<input_range... Views>
5736
  requires (view<Views> && ...) && (sizeof...(Views) > 0)
5737
  template<bool Const>
5738
  class zip_view<Views...>::iterator {
5739
  tuple<iterator_t<maybe-const<Const, Views>>...> current_; // exposition only
 
6100
  iterator_t<maybe-const<OtherConst, Views>>> && ...)
6101
  friend constexpr common_type_t<range_difference_t<maybe-const<OtherConst, Views>>...>
6102
  operator-(const sentinel& y, const iterator<OtherConst>& x);
6103
  ```
6104
 
6105
+ *Effects:* Equivalent to: `return -(x - y);`
6106
 
6107
  ### Zip transform view <a id="range.zip.transform">[[range.zip.transform]]</a>
6108
 
6109
  #### Overview <a id="range.zip.transform.overview">[[range.zip.transform.overview]]</a>
6110
 
 
6235
 
6236
  constexpr iterator(Parent& parent, ziperator<Const> inner); // exposition only
6237
 
6238
  public:
6239
  using iterator_category = see belownc; // not always present
6240
+ using iterator_concept = ziperator<Const>::iterator_concept;
6241
  using value_type =
6242
  remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
6243
  range_reference_t<maybe-const<Const, Views>>...>>;
6244
  using difference_type = range_difference_t<Base>;
6245
 
 
6538
  The name `views::adjacent<N>` denotes a range adaptor object
6539
  [[range.adaptor.object]]. Given a subexpression `E` and a constant
6540
  expression `N`, the expression `views::adjacent<N>(E)` is
6541
  expression-equivalent to
6542
 
6543
+ - `((void)E, auto(views::empty<tuple<>>))` if `N` is equal to `0` and
6544
+ `decltype((E))` models `forward_range`,
6545
  - otherwise, `adjacent_view<views::all_t<decltype((E))>, N>(E)`.
6546
 
6547
  [*Example 1*:
6548
 
6549
  ``` cpp
 
6607
  }
6608
  }
6609
 
6610
  constexpr auto size() requires sized_range<V>;
6611
  constexpr auto size() const requires sized_range<const V>;
6612
+
6613
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
6614
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
6615
  };
6616
  }
6617
  ```
6618
 
6619
  ``` cpp
 
6635
  auto sz = static_cast<CT>(ranges::size(base_));
6636
  sz -= std::min<CT>(sz, N - 1);
6637
  return static_cast<ST>(sz);
6638
  ```
6639
 
6640
+ ``` cpp
6641
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
6642
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
6643
+ ```
6644
+
6645
+ *Effects:* Equivalent to:
6646
+
6647
+ ``` cpp
6648
+ using DT = range_difference_t<decltype((base_))>;
6649
+ using CT = common_type_t<DT, size_t>;
6650
+ auto sz = static_cast<CT>(ranges::reserve_hint(base_));
6651
+ sz -= std::min<CT>(sz, N - 1);
6652
+ return to-unsigned-like(sz);
6653
+ ```
6654
+
6655
  #### Class template `adjacent_view::iterator` <a id="range.adjacent.iterator">[[range.adjacent.iterator]]</a>
6656
 
6657
  ``` cpp
6658
  namespace std::ranges {
6659
  template<forward_range V, size_t N>
 
7046
 
7047
  The name `views::adjacent_transform<N>` denotes a range adaptor object
7048
  [[range.adaptor.object]]. Given subexpressions `E` and `F` and a
7049
  constant expression `N`:
7050
 
7051
+ - If `N` is equal to `0` and `decltype((E))` models `forward_range`,
7052
+ `views::adjacent_transform<N>(E, F)` is expression-equivalent to
7053
+ `((void)E, views::zip_transform(F))`, except that the evaluations of
7054
+ `E` and `F` are indeterminately sequenced.
7055
  - Otherwise, the expression `views::adjacent_transform<N>(E, F)` is
7056
  expression-equivalent to
7057
  `adjacent_transform_view<views::all_t<decltype((E))>, decay_t<decltype((F))>, N>(E, F)`.
7058
 
7059
  [*Example 1*:
 
7094
 
7095
  public:
7096
  adjacent_transform_view() = default;
7097
  constexpr explicit adjacent_transform_view(V base, F fun);
7098
 
7099
+ constexpr V base() const & requires copy_constructible<V> { return inner_.base(); }
7100
  constexpr V base() && { return std::move(inner_).base(); }
7101
 
7102
  constexpr auto begin() {
7103
  return iterator<false>(*this, inner_.begin());
7104
  }
 
7132
  }
7133
 
7134
  constexpr auto size() const requires sized_range<const InnerView> {
7135
  return inner_.size();
7136
  }
7137
+
7138
+ constexpr auto reserve_hint() requires approximately_sized_range<InnerView> {
7139
+ return inner_.reserve_hint();
7140
+ }
7141
+
7142
+ constexpr auto reserve_hint() const requires approximately_sized_range<const InnerView> {
7143
+ return inner_.reserve_hint();
7144
+ }
7145
  };
7146
  }
7147
  ```
7148
 
7149
  ``` cpp
 
7170
 
7171
  constexpr iterator(Parent& parent, inner-iterator<Const> inner); // exposition only
7172
 
7173
  public:
7174
  using iterator_category = see below;
7175
+ using iterator_concept = inner-iterator<Const>::iterator_concept;
7176
  using value_type =
7177
  remove_cvref_t<invoke_result_t<maybe-const<Const, F>&,
7178
  REPEAT(range_reference_t<Base>, N)...>>;
7179
  using difference_type = range_difference_t<Base>;
7180
 
 
7444
  template<bool OtherConst>
7445
  requires sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
7446
  friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
7447
  ```
7448
 
7449
+ *Effects:* Equivalent to: `return x.`*`inner_`*` == y.`*`inner_`*`;`
7450
 
7451
  ``` cpp
7452
  template<bool OtherConst>
7453
  requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
7454
  friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
 
7458
  requires sized_sentinel_for<inner-sentinel<Const>, inner-iterator<OtherConst>>
7459
  friend constexpr range_difference_t<maybe-const<OtherConst, InnerView>>
7460
  operator-(const sentinel& x, const iterator<OtherConst>& y);
7461
  ```
7462
 
7463
+ *Effects:* Equivalent to: `return x.`*`inner_`*` - y.`*`inner_`*`;`
7464
 
7465
  ### Chunk view <a id="range.chunk">[[range.chunk]]</a>
7466
 
7467
  #### Overview <a id="range.chunk.overview">[[range.chunk.overview]]</a>
7468
 
 
7531
  constexpr outer-iterator begin();
7532
  constexpr default_sentinel_t end() const noexcept;
7533
 
7534
  constexpr auto size() requires sized_range<V>;
7535
  constexpr auto size() const requires sized_range<const V>;
7536
+
7537
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
7538
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
7539
  };
7540
 
7541
  template<class R>
7542
  chunk_view(R&&, range_difference_t<R>) -> chunk_view<views::all_t<R>>;
7543
  }
 
7579
 
7580
  ``` cpp
7581
  return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
7582
  ```
7583
 
7584
+ ``` cpp
7585
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
7586
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
7587
+ ```
7588
+
7589
+ *Effects:* Equivalent to:
7590
+
7591
+ ``` cpp
7592
+ auto s = static_cast<range_difference_t<decltype((base_))>>(ranges::reserve_hint(base_));
7593
+ return to-unsigned-like(div-ceil(s, n_));
7594
+ ```
7595
+
7596
  #### Class `chunk_view::outer-iterator` <a id="range.chunk.outer.iter">[[range.chunk.outer.iter]]</a>
7597
 
7598
  ``` cpp
7599
  namespace std::ranges {
7600
  template<view V>
 
7710
  constexpr inner-iterator begin() const noexcept;
7711
  constexpr default_sentinel_t end() const noexcept;
7712
 
7713
  constexpr auto size() const
7714
  requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
7715
+
7716
+ constexpr auto reserve_hint() const noexcept;
7717
  };
7718
  }
7719
  ```
7720
 
7721
  ``` cpp
 
7746
  ``` cpp
7747
  return to-unsigned-like(ranges::min(parent_->remainder_,
7748
  ranges::end(parent_->base_) - *parent_->current_));
7749
  ```
7750
 
7751
+ ``` cpp
7752
+ constexpr auto reserve_hint() const noexcept;
7753
+ ```
7754
+
7755
+ *Effects:* Equivalent to:
7756
+
7757
+ ``` cpp
7758
+ return to-unsigned-like(parent_->remainder_);
7759
+ ```
7760
+
7761
  #### Class `chunk_view::inner-iterator` <a id="range.chunk.inner.iter">[[range.chunk.inner.iter]]</a>
7762
 
7763
  ``` cpp
7764
  namespace std::ranges {
7765
  template<view V>
 
7934
  }
7935
  }
7936
 
7937
  constexpr auto size() requires sized_range<V>;
7938
  constexpr auto size() const requires sized_range<const V>;
7939
+
7940
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
7941
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
7942
  };
7943
  }
7944
  ```
7945
 
7946
  ``` cpp
 
7961
 
7962
  ``` cpp
7963
  return to-unsigned-like(div-ceil(ranges::distance(base_), n_));
7964
  ```
7965
 
7966
+ ``` cpp
7967
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
7968
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
7969
+ ```
7970
+
7971
+ *Effects:* Equivalent to:
7972
+
7973
+ ``` cpp
7974
+ auto s = static_cast<range_difference_t<decltype((base_))>>(ranges::reserve_hint(base_));
7975
+ return to-unsigned-like(div-ceil(s, n_));
7976
+ ```
7977
+
7978
  #### Class template `chunk_view::iterator` for forward ranges <a id="range.chunk.fwd.iter">[[range.chunk.fwd.iter]]</a>
7979
 
7980
  ``` cpp
7981
  namespace std::ranges {
7982
  template<view V>
 
8349
  requires (!(simple-view<V> && slide-caches-nothing<const V>));
8350
  constexpr auto end() const requires slide-caches-nothing<const V>;
8351
 
8352
  constexpr auto size() requires sized_range<V>;
8353
  constexpr auto size() const requires sized_range<const V>;
8354
+
8355
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
8356
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
8357
  };
8358
 
8359
  template<class R>
8360
  slide_view(R&&, range_difference_t<R>) -> slide_view<views::all_t<R>>;
8361
  }
 
8439
  auto sz = ranges::distance(base_) - n_ + 1;
8440
  if (sz < 0) sz = 0;
8441
  return to-unsigned-like(sz);
8442
  ```
8443
 
8444
+ ``` cpp
8445
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
8446
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
8447
+ ```
8448
+
8449
+ *Effects:* Equivalent to:
8450
+
8451
+ ``` cpp
8452
+ auto sz = static_cast<range_difference_t<decltype((base_))>>(ranges::reserve_hint(base_)) -
8453
+ n_ + 1;
8454
+ if (sz < 0) sz = 0;
8455
+ return to-unsigned-like(sz);
8456
+ ```
8457
+
8458
  #### Class template `slide_view::iterator` <a id="range.slide.iterator">[[range.slide.iterator]]</a>
8459
 
8460
  ``` cpp
8461
  namespace std::ranges {
8462
  template<forward_range V>
 
9120
  }
9121
  }
9122
 
9123
  constexpr auto size() requires sized_range<V>;
9124
  constexpr auto size() const requires sized_range<const V>;
9125
+
9126
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
9127
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
9128
  };
9129
 
9130
  template<class R>
9131
  stride_view(R&&, range_difference_t<R>) -> stride_view<views::all_t<R>>;
9132
  }
 
9156
 
9157
  ``` cpp
9158
  return to-unsigned-like(div-ceil(ranges::distance(base_), stride_));
9159
  ```
9160
 
9161
+ ``` cpp
9162
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
9163
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
9164
+ ```
9165
+
9166
+ *Effects:* Equivalent to:
9167
+
9168
+ ``` cpp
9169
+ auto s = static_cast<range_difference_t<decltype((base_))>>(ranges::reserve_hint(base_));
9170
+ return to-unsigned-like(div-ceil(s, stride_));
9171
+ ```
9172
+
9173
  #### Class template `stride_view::iterator` <a id="range.stride.iterator">[[range.stride.iterator]]</a>
9174
 
9175
  ``` cpp
9176
  namespace std::ranges {
9177
  template<input_range V>
 
9329
 
9330
  ``` cpp
9331
  constexpr void operator++(int);
9332
  ```
9333
 
9334
+ *Effects:* Equivalent to `++*this;`
9335
 
9336
  ``` cpp
9337
  constexpr iterator operator++(int) requires forward_range<Base>;
9338
  ```
9339
 
 
9571
  concept cartesian-product-is-bidirectional = // exposition only
9572
  (bidirectional_range<maybe-const<Const, First>> && ... &&
9573
  (bidirectional_range<maybe-const<Const, Vs>>
9574
  && cartesian-product-common-arg<maybe-const<Const, Vs>>));
9575
 
9576
+ template<class First, class...>
9577
  concept cartesian-product-is-common = // exposition only
9578
  cartesian-product-common-arg<First>;
9579
 
9580
  template<class... Vs>
9581
  concept cartesian-product-is-sized = // exposition only
 
10114
  the following expressions:
10115
 
10116
  - `noexcept(ranges::iter_swap(std::get<`i`>(l.`*`current_`*`), std::get<`i`>(r.`*`current_`*`)))`
10117
  for every integer 0 ≤ i ≤ `sizeof...(Vs)`.
10118
 
10119
+ ### Cache latest view <a id="range.cache.latest">[[range.cache.latest]]</a>
10120
+
10121
+ #### Overview <a id="range.cache.latest.overview">[[range.cache.latest.overview]]</a>
10122
+
10123
+ `cache_latest_view` caches the last-accessed element of its underlying
10124
+ sequence so that the element does not have to be recomputed on repeated
10125
+ access.
10126
+
10127
+ [*Note 1*: This is useful if computation of the element to produce is
10128
+ expensive. — *end note*]
10129
+
10130
+ The name `views::cache_latest` denotes a range adaptor object
10131
+ [[range.adaptor.object]]. Let `E` be an expression. The expression
10132
+ `views::cache_latest(E)` is expression-equivalent to
10133
+ `cache_latest_view(E)`.
10134
+
10135
+ #### Class template `cache_latest_view` <a id="range.cache.latest.view">[[range.cache.latest.view]]</a>
10136
+
10137
+ ``` cpp
10138
+ namespace std::ranges {
10139
+ template<input_range V>
10140
+ requires view<V>
10141
+ class cache_latest_view : public view_interface<cache_latest_view<V>> {
10142
+ V base_ = V(); // exposition only
10143
+ using cache-t = conditional_t<is_reference_v<range_reference_t<V>>, // exposition only
10144
+ add_pointer_t<range_reference_t<V>>,
10145
+ range_reference_t<V>>;
10146
+
10147
+ non-propagating-cache<cache-t> cache_; // exposition only
10148
+
10149
+ // [range.cache.latest.iterator], class cache_latest_view::iterator
10150
+ class iterator; // exposition only
10151
+ // [range.cache.latest.sentinel], class cache_latest_view::sentinel
10152
+ class sentinel; // exposition only
10153
+
10154
+ public:
10155
+ cache_latest_view() requires default_initializable<V> = default;
10156
+ constexpr explicit cache_latest_view(V base);
10157
+
10158
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
10159
+ constexpr V base() && { return std::move(base_); }
10160
+
10161
+ constexpr auto begin();
10162
+ constexpr auto end();
10163
+
10164
+ constexpr auto size() requires sized_range<V>;
10165
+ constexpr auto size() const requires sized_range<const V>;
10166
+
10167
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
10168
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
10169
+ };
10170
+
10171
+ template<class R>
10172
+ cache_latest_view(R&&) -> cache_latest_view<views::all_t<R>>;
10173
+ }
10174
+ ```
10175
+
10176
+ ``` cpp
10177
+ constexpr explicit cache_latest_view(V base);
10178
+ ```
10179
+
10180
+ *Effects:* Initializes *base\_* with `std::move(base)`.
10181
+
10182
+ ``` cpp
10183
+ constexpr auto begin();
10184
+ ```
10185
+
10186
+ *Effects:* Equivalent to: `return `*`iterator`*`(*this);`
10187
+
10188
+ ``` cpp
10189
+ constexpr auto end();
10190
+ ```
10191
+
10192
+ *Effects:* Equivalent to: `return `*`sentinel`*`(*this);`
10193
+
10194
+ ``` cpp
10195
+ constexpr auto size() requires sized_range<V>;
10196
+ constexpr auto size() const requires sized_range<const V>;
10197
+ ```
10198
+
10199
+ *Effects:* Equivalent to: `return ranges::size(`*`base_`*`);`
10200
+
10201
+ ``` cpp
10202
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
10203
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
10204
+ ```
10205
+
10206
+ *Effects:* Equivalent to: `return ranges::reserve_hint(`*`base_`*`);`
10207
+
10208
+ #### Class `cache_latest_view::iterator` <a id="range.cache.latest.iterator">[[range.cache.latest.iterator]]</a>
10209
+
10210
+ ``` cpp
10211
+ namespace std::ranges {
10212
+ template<input_range V>
10213
+ requires view<V>
10214
+ class cache_latest_view<V>::iterator {
10215
+ cache_latest_view* parent_; // exposition only
10216
+ iterator_t<V> current_; // exposition only
10217
+
10218
+ constexpr explicit iterator(cache_latest_view& parent); // exposition only
10219
+
10220
+ public:
10221
+ using difference_type = range_difference_t<V>;
10222
+ using value_type = range_value_t<V>;
10223
+ using iterator_concept = input_iterator_tag;
10224
+
10225
+ iterator(iterator&&) = default;
10226
+ iterator& operator=(iterator&&) = default;
10227
+
10228
+ constexpr iterator_t<V> base() &&;
10229
+ constexpr const iterator_t<V>& base() const & noexcept;
10230
+
10231
+ constexpr range_reference_t<V>& operator*() const;
10232
+
10233
+ constexpr iterator& operator++();
10234
+ constexpr void operator++(int);
10235
+
10236
+ friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
10237
+ noexcept(noexcept(ranges::iter_move(i.current_)));
10238
+
10239
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
10240
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
10241
+ requires indirectly_swappable<iterator_t<V>>;
10242
+ };
10243
+ }
10244
+ ```
10245
+
10246
+ ``` cpp
10247
+ constexpr explicit iterator(cache_latest_view& parent);
10248
+ ```
10249
+
10250
+ *Effects:* Initializes *current\_* with
10251
+ `ranges::begin(parent.`*`base_`*`)` and *parent\_* with
10252
+ `addressof(parent)`.
10253
+
10254
+ ``` cpp
10255
+ constexpr iterator_t<V> base() &&;
10256
+ ```
10257
+
10258
+ *Returns:* `std::move(`*`current_`*`)`.
10259
+
10260
+ ``` cpp
10261
+ constexpr const iterator_t<V>& base() const & noexcept;
10262
+ ```
10263
+
10264
+ *Returns:* *current\_*.
10265
+
10266
+ ``` cpp
10267
+ constexpr iterator& operator++();
10268
+ ```
10269
+
10270
+ *Effects:* Equivalent to:
10271
+
10272
+ ``` cpp
10273
+ parent_->cache_.reset();
10274
+ ++current_;
10275
+ return *this;
10276
+ ```
10277
+
10278
+ ``` cpp
10279
+ constexpr void operator++(int);
10280
+ ```
10281
+
10282
+ *Effects:* Equivalent to: `++*this`.
10283
+
10284
+ ``` cpp
10285
+ constexpr range_reference_t<V>& operator*() const;
10286
+ ```
10287
+
10288
+ *Effects:* Equivalent to:
10289
+
10290
+ ``` cpp
10291
+ if constexpr (is_reference_v<range_reference_t<V>>) {
10292
+ if (!parent_->cache_) {
10293
+ parent_->cache_ = addressof(as-lvalue(*current_));
10294
+ }
10295
+ return **parent_->cache_;
10296
+ } else {
10297
+ if (!parent_->cache_) {
10298
+ parent_->cache_.emplace-deref(current_);
10299
+ }
10300
+ return *parent_->cache_;
10301
+ }
10302
+ ```
10303
+
10304
+ [*Note 1*: Evaluations of `operator*` on the same iterator object can
10305
+ conflict [[intro.races]]. — *end note*]
10306
+
10307
+ ``` cpp
10308
+ friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i)
10309
+ noexcept(noexcept(ranges::iter_move(i.current_)));
10310
+ ```
10311
+
10312
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
10313
+
10314
+ ``` cpp
10315
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
10316
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
10317
+ requires indirectly_swappable<iterator_t<V>>;
10318
+ ```
10319
+
10320
+ *Effects:* Equivalent to
10321
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`)`.
10322
+
10323
+ #### Class `cache_latest_view::sentinel` <a id="range.cache.latest.sentinel">[[range.cache.latest.sentinel]]</a>
10324
+
10325
+ ``` cpp
10326
+ namespace std::ranges {
10327
+ template<input_range V>
10328
+ requires view<V>
10329
+ class cache_latest_view<V>::sentinel {
10330
+ sentinel_t<V> end_ = sentinel_t<V>(); // exposition only
10331
+
10332
+ constexpr explicit sentinel(cache_latest_view& parent); // exposition only
10333
+
10334
+ public:
10335
+ sentinel() = default;
10336
+
10337
+ constexpr sentinel_t<V> base() const;
10338
+
10339
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
10340
+
10341
+ friend constexpr range_difference_t<V> operator-(const iterator& x, const sentinel& y)
10342
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10343
+ friend constexpr range_difference_t<V> operator-(const sentinel& x, const iterator& y)
10344
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10345
+ };
10346
+ }
10347
+ ```
10348
+
10349
+ ``` cpp
10350
+ constexpr explicit sentinel(cache_latest_view& parent);
10351
+ ```
10352
+
10353
+ *Effects:* Initializes *end\_* with `ranges::end(parent.`*`base_`*`)`.
10354
+
10355
+ ``` cpp
10356
+ constexpr sentinel_t<V> base() const;
10357
+ ```
10358
+
10359
+ *Returns:* *end\_*.
10360
+
10361
+ ``` cpp
10362
+ friend constexpr bool operator==(const iterator& x, const sentinel& y);
10363
+ ```
10364
+
10365
+ *Returns:* `x.`*`current_`*` == y.`*`end_`*.
10366
+
10367
+ ``` cpp
10368
+ friend constexpr range_difference_t<V> operator-(const iterator& x, const sentinel& y)
10369
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10370
+ ```
10371
+
10372
+ *Returns:* `x.`*`current_`*` - y.`*`end_`*.
10373
+
10374
+ ``` cpp
10375
+ friend constexpr range_difference_t<V> operator-(const sentinel& x, const iterator& y)
10376
+ requires sized_sentinel_for<sentinel_t<V>, iterator_t<V>>;
10377
+ ```
10378
+
10379
+ *Returns:* `x.`*`end_`*` - y.`*`current_`*.
10380
+
10381
+ ### To input view <a id="range.to.input">[[range.to.input]]</a>
10382
+
10383
+ #### Overview <a id="range.to.input.overview">[[range.to.input.overview]]</a>
10384
+
10385
+ `to_input_view` presents a view of an underlying sequence as an
10386
+ input-only non-common range.
10387
+
10388
+ [*Note 1*: This is useful to avoid overhead that can be necessary to
10389
+ provide support for the operations needed for greater iterator
10390
+ strength. — *end note*]
10391
+
10392
+ The name `views::to_input` denotes a range adaptor object
10393
+ [[range.adaptor.object]]. Let `E` be an expression and let `T` be
10394
+ `decltype((E))`. The expression `views::to_input(E)` is
10395
+ expression-equivalent to:
10396
+
10397
+ - `views::all(E)` if `T` models `input_range`, does not satisfy
10398
+ `common_range`, and does not satisfy `forward_range`.
10399
+ - Otherwise, `to_input_view(E)`.
10400
+
10401
+ #### Class template `to_input_view` <a id="range.to.input.view">[[range.to.input.view]]</a>
10402
+
10403
+ ``` cpp
10404
+ namespace std::ranges {
10405
+ template<input_range V>
10406
+ requires view<V>
10407
+ class to_input_view : public view_interface<to_input_view<V>> {
10408
+ V base_ = V(); // exposition only
10409
+
10410
+ // [range.to.input.iterator], class template to_input_view::iterator
10411
+ template<bool Const> class iterator; // exposition only
10412
+
10413
+ public:
10414
+ to_input_view() requires default_initializable<V> = default;
10415
+ constexpr explicit to_input_view(V base);
10416
+
10417
+ constexpr V base() const & requires copy_constructible<V> { return base_; }
10418
+ constexpr V base() && { return std::move(base_); }
10419
+
10420
+ constexpr auto begin() requires (!simple-view<V>);
10421
+ constexpr auto begin() const requires range<const V>;
10422
+
10423
+ constexpr auto end() requires (!simple-view<V>);
10424
+ constexpr auto end() const requires range<const V>;
10425
+
10426
+ constexpr auto size() requires sized_range<V>;
10427
+ constexpr auto size() const requires sized_range<const V>;
10428
+
10429
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
10430
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
10431
+ };
10432
+
10433
+ template<class R>
10434
+ to_input_view(R&&) -> to_input_view<views::all_t<R>>;
10435
+ }
10436
+ ```
10437
+
10438
+ ``` cpp
10439
+ constexpr explicit to_input_view(V base);
10440
+ ```
10441
+
10442
+ *Effects:* Initializes *base\_* with `std::move(base)`.
10443
+
10444
+ ``` cpp
10445
+ constexpr auto begin() requires (!simple-view<V>);
10446
+ ```
10447
+
10448
+ *Effects:* Equivalent to:
10449
+ `return `*`iterator`*`<false>(ranges::begin(`*`base_`*`));`
10450
+
10451
+ ``` cpp
10452
+ constexpr auto begin() const requires range<const V>;
10453
+ ```
10454
+
10455
+ *Effects:* Equivalent to:
10456
+ `return `*`iterator`*`<true>(ranges::begin(`*`base_`*`));`
10457
+
10458
+ ``` cpp
10459
+ constexpr auto end() requires (!simple-view<V>);
10460
+ constexpr auto end() const requires range<const V>;
10461
+ ```
10462
+
10463
+ *Effects:* Equivalent to: `return ranges::end(`*`base_`*`);`
10464
+
10465
+ ``` cpp
10466
+ constexpr auto size() requires sized_range<V>;
10467
+ constexpr auto size() const requires sized_range<const V>;
10468
+ ```
10469
+
10470
+ *Effects:* Equivalent to: `return ranges::size(`*`base_`*`);`
10471
+
10472
+ ``` cpp
10473
+ constexpr auto reserve_hint() requires approximately_sized_range<V>;
10474
+ constexpr auto reserve_hint() const requires approximately_sized_range<const V>;
10475
+ ```
10476
+
10477
+ *Effects:* Equivalent to: `return ranges::reserve_hint(`*`base_`*`);`
10478
+
10479
+ #### Class template `to_input_view::iterator` <a id="range.to.input.iterator">[[range.to.input.iterator]]</a>
10480
+
10481
+ ``` cpp
10482
+ namespace std::ranges {
10483
+ template<input_range V>
10484
+ requires view<V>
10485
+ template<bool Const>
10486
+ class to_input_view<V>::iterator {
10487
+ using Base = maybe-const<Const, V>; // exposition only
10488
+
10489
+ iterator_t<Base> current_ = iterator_t<Base>(); // exposition only
10490
+
10491
+ constexpr explicit iterator(iterator_t<Base> current); // exposition only
10492
+
10493
+ public:
10494
+ using difference_type = range_difference_t<Base>;
10495
+ using value_type = range_value_t<Base>;
10496
+ using iterator_concept = input_iterator_tag;
10497
+
10498
+ iterator() requires default_initializable<iterator_t<Base>> = default;
10499
+
10500
+ iterator(iterator&&) = default;
10501
+ iterator& operator=(iterator&&) = default;
10502
+
10503
+ constexpr iterator(iterator<!Const> i)
10504
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
10505
+
10506
+ constexpr iterator_t<Base> base() &&;
10507
+ constexpr const iterator_t<Base>& base() const & noexcept;
10508
+
10509
+ constexpr decltype(auto) operator*() const { return *current_; }
10510
+
10511
+ constexpr iterator& operator++();
10512
+ constexpr void operator++(int);
10513
+
10514
+ friend constexpr bool operator==(const iterator& x, const sentinel_t<Base>& y);
10515
+
10516
+ friend constexpr difference_type operator-(const sentinel_t<Base>& y, const iterator& x)
10517
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10518
+ friend constexpr difference_type operator-(const iterator& x, const sentinel_t<Base>& y)
10519
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10520
+
10521
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
10522
+ noexcept(noexcept(ranges::iter_move(i.current_)));
10523
+
10524
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
10525
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
10526
+ requires indirectly_swappable<iterator_t<Base>>;
10527
+ };
10528
+ }
10529
+ ```
10530
+
10531
+ ``` cpp
10532
+ constexpr explicit iterator(iterator_t<Base> current);
10533
+ ```
10534
+
10535
+ *Effects:* Initializes *current\_* with `std::move(current)`.
10536
+
10537
+ ``` cpp
10538
+ constexpr iterator(iterator<!Const> i)
10539
+ requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;
10540
+ ```
10541
+
10542
+ *Effects:* Initializes *current\_* with `std::move(i.`*`current_`*`)`.
10543
+
10544
+ ``` cpp
10545
+ constexpr iterator_t<Base> base() &&;
10546
+ ```
10547
+
10548
+ *Returns:* `std::move(`*`current_`*`)`.
10549
+
10550
+ ``` cpp
10551
+ constexpr const iterator_t<Base>& base() const & noexcept;
10552
+ ```
10553
+
10554
+ *Returns:* *current\_*.
10555
+
10556
+ ``` cpp
10557
+ constexpr iterator& operator++();
10558
+ ```
10559
+
10560
+ *Effects:* Equivalent to:
10561
+
10562
+ ``` cpp
10563
+ ++current_;
10564
+ return *this;
10565
+ ```
10566
+
10567
+ ``` cpp
10568
+ constexpr void operator++(int);
10569
+ ```
10570
+
10571
+ *Effects:* Equivalent to: `++*this;`
10572
+
10573
+ ``` cpp
10574
+ friend constexpr bool operator==(const iterator& x, const sentinel_t<Base>& y);
10575
+ ```
10576
+
10577
+ *Returns:* `x.`*`current_`*` == y`.
10578
+
10579
+ ``` cpp
10580
+ friend constexpr difference_type operator-(const sentinel_t<Base>& y, const iterator& x)
10581
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10582
+ ```
10583
+
10584
+ *Returns:* `y - x.`*`current_`*.
10585
+
10586
+ ``` cpp
10587
+ friend constexpr difference_type operator-(const iterator& x, const sentinel_t<Base>& y)
10588
+ requires sized_sentinel_for<sentinel_t<Base>, iterator_t<Base>>;
10589
+ ```
10590
+
10591
+ *Returns:* `x.`*`current_`*` - y`.
10592
+
10593
+ ``` cpp
10594
+ friend constexpr range_rvalue_reference_t<Base> iter_move(const iterator& i)
10595
+ noexcept(noexcept(ranges::iter_move(i.current_)));
10596
+ ```
10597
+
10598
+ *Effects:* Equivalent to: `return ranges::iter_move(i.`*`current_`*`);`
10599
+
10600
+ ``` cpp
10601
+ friend constexpr void iter_swap(const iterator& x, const iterator& y)
10602
+ noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
10603
+ requires indirectly_swappable<iterator_t<Base>>;
10604
+ ```
10605
+
10606
+ *Effects:* Equivalent to:
10607
+ `ranges::iter_swap(x.`*`current_`*`, y.`*`current_`*`);`
10608
+