24 Ranges library [ranges]

24.7 Range adaptors [range.adaptors]

24.7.11 Split view [range.split]

24.7.11.3 Class template split_­view​::​outer-iterator [range.split.outer]

namespace std::ranges {
  template<input_range V, forward_range Pattern>
    requires view<V> && view<Pattern> &&
             indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
             (forward_range<V> || tiny-range<Pattern>)
  template<bool Const>
  struct split_view<V, Pattern>::outer-iterator {
  private:
    using Parent =                          // exposition only
      conditional_t<Const, const split_view, split_view>;
    using Base   =                          // exposition only
      conditional_t<Const, const V, V>;
    Parent* parent_ = nullptr;              // exposition only
    iterator_t<Base> current_ =             // exposition only, present only if V models forward_­range
      iterator_t<Base>();

  public:
    using iterator_concept  =
      conditional_t<forward_range<Base>, forward_iterator_tag, input_iterator_tag>;
    using iterator_category = input_iterator_tag;
    // [range.split.outer.value], class split_­view​::​outer-iterator​::​value_­type
    struct value_type;
    using difference_type   = range_difference_t<Base>;

    outer-iterator() = default;
    constexpr explicit outer-iterator(Parent& parent)
      requires (!forward_range<Base>);
    constexpr outer-iterator(Parent& parent, iterator_t<Base> current)
      requires forward_range<Base>;
    constexpr outer-iterator(outer-iterator<!Const> i)
      requires Const && convertible_to<iterator_t<V>, iterator_t<Base>>;

    constexpr value_type operator*() const;

    constexpr outer-iterator& operator++();
    constexpr decltype(auto) operator++(int) {
      if constexpr (forward_range<Base>) {
        auto tmp = *this;
        ++*this;
        return tmp;
      } else
        ++*this;
    }

    friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y)
      requires forward_range<Base>;

    friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
  };
}
Many of the following specifications refer to the notional member current of outer-iterator.
current is equivalent to current_­ if V models forward_­range, and parent_­->current_­ otherwise.
constexpr explicit outer-iterator(Parent& parent) requires (!forward_­range<Base>);
Effects: Initializes parent_­ with addressof(parent).
constexpr outer-iterator(Parent& parent, iterator_t<Base> current) requires forward_­range<Base>;
Effects: Initializes parent_­ with addressof(parent) and current_­ with std​::​move(current).
constexpr outer-iterator(outer-iterator<!Const> i) requires Const && convertible_­to<iterator_t<V>, iterator_t<Base>>;
Effects: Initializes parent_­ with i.parent_­ and current_­ with std​::​move(i.current_­).
constexpr value_type operator*() const;
Effects: Equivalent to: return value_­type{*this};
constexpr outer-iterator& operator++();
Effects: Equivalent to:
const auto end = ranges::end(parent_->base_);
if (current == end) return *this;
const auto [pbegin, pend] = subrange{parent_->pattern_};
if (pbegin == pend) ++current;
else {
  do {
    auto [b, p] = ranges::mismatch(std::move(current), end, pbegin, pend);
    current = std::move(b);
    if (p == pend) {
      break;            // The pattern matched; skip it
    }
  } while (++current != end);
}
return *this;
friend constexpr bool operator==(const outer-iterator& x, const outer-iterator& y) requires forward_­range<Base>;
Effects: Equivalent to: return x.current_­ == y.current_­;
friend constexpr bool operator==(const outer-iterator& x, default_sentinel_t);
Effects: Equivalent to: return x.current == ranges​::​end(x.parent_­->base_­);