23 Ranges library [ranges]

23.8 Range adaptors [range.adaptors]

23.8.4 Filter view [range.filter]

23.8.4.1 Overview [range.filter.overview]

filter_­view presents a View of an underlying sequence without the elements that fail to satisfy a predicate.
[Example
:
vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };
filter_view evens{is, [](int i) { return 0 == i % 2; }};
for (int i : evens)
  cout << i << ' '; // prints: 0 2 4 6
end example
]

23.8.4.2 Class template filter_­view [range.filter.view]

namespace std::ranges {
  template<InputRange V, IndirectUnaryPredicate<iterator_t<V>> Pred>
    requires View<V> && is_object_v<Pred>
  class filter_view : public view_interface<filter_view<V, Pred>> {
  private:
    V base_ = V();              // exposition only
    semiregular<Pred> pred_;    // exposition only

    class iterator;             // exposition only
    class sentinel;             // exposition only

  public:
    filter_view() = default;
    constexpr filter_view(V base, Pred pred);
    template<InputRange R>
      requires ViewableRange<R> && Constructible<V, all_view<R>>
    constexpr filter_view(R&& r, Pred pred);

    constexpr V base() const;

    constexpr iterator begin();
    constexpr auto end() {
      if constexpr (CommonRange<V>)
        return iterator{*this, ranges::end(base_)};
      else
        return sentinel{*this};
    }
  };

  template<class R, class Pred>
    filter_view(R&&, Pred) -> filter_view<all_view<R>, Pred>;
}
constexpr filter_view(V base, Pred pred);
Effects: Initializes base_­ with std::move(base) and initializes pred_­ with std::move(pred).
template<InputRange R> requires ViewableRange<R> && Constructible<V, all_view<R>> constexpr filter_view(R&& r, Pred pred);
Effects: Initializes base_­ with view::all(std::forward<R>(r)) and initializes pred_­ with std::​move(pred).
constexpr V base() const;
Effects: Equivalent to: return base_­;
constexpr iterator begin();
Expects: pred_­.has_­value().
Returns: {*this, ranges::find_­if(base_­, ref(*pred_­))}.
Remarks: In order to provide the amortized constant time complexity required by the Range concept, this function caches the result within the filter_­view for use on subsequent calls.

23.8.4.3 Class filter_­view​::​iterator [range.filter.iterator]

namespace std::ranges {
  template<class V, class Pred>
  class filter_view<V, Pred>::iterator {
  private:
    iterator_t<V> current_ = iterator_t<V>();   // exposition only
    filter_view* parent_ = nullptr;             // exposition only
  public:
    using iterator_concept  = see below;
    using iterator_category = see below;
    using value_type        = iter_value_t<iterator_t<V>>;
    using difference_type   = iter_difference_t<iterator_t<V>>;

    iterator() = default;
    constexpr iterator(filter_view& parent, iterator_t<V> current);

    constexpr iterator_t<V> base() const;
    constexpr iter_reference_t<iterator_t<V>> operator*() const;
    constexpr iterator_t<V> operator->() const
      requires has-arrow<iterator_t<V>>;

    constexpr iterator& operator++();
    constexpr void operator++(int);
    constexpr iterator operator++(int) requires ForwardRange<V>;

    constexpr iterator& operator--() requires BidirectionalRange<V>;
    constexpr iterator operator--(int) requires BidirectionalRange<V>;

    friend constexpr bool operator==(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<V>>;
    friend constexpr bool operator!=(const iterator& x, const iterator& y)
      requires EqualityComparable<iterator_t<V>>;

    friend constexpr iter_rvalue_reference_t<iterator_t<V>> iter_move(const iterator& i)
      noexcept(noexcept(ranges::iter_move(i.current_)));
    friend constexpr void iter_swap(const iterator& x, const iterator& y)
      noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
      requires IndirectlySwappable<iterator_t<V>>;
  };
}
Modification of the element a filter_­view::iterator denotes is permitted, but results in undefined behavior if the resulting value does not satisfy the filter predicate.
iterator::iterator_­concept is defined as follows:
  • If V models BidirectionalRange, then iterator_­concept denotes bidirectional_­iterator_­tag.
  • Otherwise, if V models ForwardRange, then iterator_­concept denotes forward_­iterator_­tag.
  • Otherwise, iterator_­concept denotes input_­iterator_­tag.
iterator::iterator_­category is defined as follows:
  • Let C denote the type iterator_­traits<iterator_­t<V>>::iterator_­category.
  • If C models DerivedFrom<bidirectional_­iterator_­tag>, then iterator_­category denotes bidirectional_­iterator_­tag.
  • Otherwise, if C models DerivedFrom<forward_­iterator_­tag>, then iterator_­category denotes forward_­iterator_­tag.
  • Otherwise, iterator_­category denotes input_­iterator_­tag.
constexpr iterator(filter_view& parent, iterator_t<V> current);
Effects: Initializes current_­ with current and parent_­ with addressof(parent).
constexpr iterator_t<V> base() const;
Effects: Equivalent to: return current_­;
constexpr iter_reference_t<iterator_t<V>> operator*() const;
Effects: Equivalent to: return *current_­;
constexpr iterator_t<V> operator->() const requires has-arrow<iterator_t<V>>;
Effects: Equivalent to: return current_­;
constexpr iterator& operator++();
Effects: Equivalent to:
current_ = ranges::find_if(++current_, ranges::end(parent_->base_), ref(*parent_->pred_));
return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr iterator operator++(int) requires ForwardRange<V>;
Effects: Equivalent to:
auto tmp = *this;
++*this;
return tmp;
constexpr iterator& operator--() requires BidirectionalRange<V>;
Effects: Equivalent to:
do
  --current_;
while (!invoke(*parent_->pred_, *current_));
return *this;
constexpr iterator operator--(int) requires BidirectionalRange<V>;
Effects: Equivalent to:
auto tmp = *this;
--*this;
return tmp;
friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<V>>;
Effects: Equivalent to: return x.current_­ == y.current_­;
friend constexpr bool operator!=(const iterator& x, const iterator& y) requires EqualityComparable<iterator_t<V>>;
Effects: Equivalent to: return !(x == y);
friend constexpr iter_rvalue_reference_t<iterator_t<V>> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)));
Effects: Equivalent to: return ranges::iter_­move(i.current_­);
friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires IndirectlySwappable<iterator_t<V>>;
Effects: Equivalent to ranges::iter_­swap(x.current_­, y.current_­).

23.8.4.4 Class filter_­view​::​sentinel [range.filter.sentinel]

namespace std::ranges {
  template<class V, class Pred>
  class filter_view<V, Pred>::sentinel {
  private:
    sentinel_t<V> end_ = sentinel_t<V>();       // exposition only
  public:
    sentinel() = default;
    constexpr explicit sentinel(filter_view& parent);

    constexpr sentinel_t<V> base() const;

    friend constexpr bool operator==(const iterator& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator& y);
    friend constexpr bool operator!=(const iterator& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator& y);
  };
}
constexpr explicit sentinel(filter_view& parent);
Effects: Initializes end_­ with ranges::end(parent).
constexpr sentinel_t<V> base() const;
Effects: Equivalent to: return end_­;
friend constexpr bool operator==(const iterator& x, const sentinel& y);
Effects: Equivalent to: return x.current_­ == y.end_­;
friend constexpr bool operator==(const sentinel& x, const iterator& y);
Effects: Equivalent to: return y == x;
friend constexpr bool operator!=(const iterator& x, const sentinel& y);
Effects: Equivalent to: return !(x == y);
friend constexpr bool operator!=(const sentinel& x, const iterator& y);
Effects: Equivalent to: return !(y == x);

23.8.4.5 view​::​filter [range.filter.adaptor]

The name view::filter denotes a range adaptor object ([range.adaptor.object]).
For some subexpressions E and P, the expression view::filter(E, P) is expression-equivalent to filter_­view{E, P}.