[range.filter] (original) (raw)

25 Ranges library [ranges]

25.7 Range adaptors [range.adaptors]

25.7.8 Filter view [range.filter]

25.7.8.1 Overview [range.filter.overview]

filter_view presents a view of the elements of an underlying sequence that satisfy a predicate.

Given subexpressions E and P, the expression views​::​filter(E, P) is expression-equivalent tofilter_view(E, P).

[Example 1: vector<int> is{ 0, 1, 2, 3, 4, 5, 6 };auto evens = views::filter(is, [](int i) { return 0 == i % 2; });for (int i : evens) cout << i << ' '; — _end example_]

25.7.8.2 Class template filter_view [range.filter.view]

namespace std::ranges { template<input_range V, indirect_unary_predicate<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(); movable-box<Pred> pred_; class iterator; class sentinel; public: filter_view() requires default_initializable<V> && default_initializable<Pred> = default;constexpr explicit filter_view(V base, Pred pred);constexpr V base() const & requires copy_constructible<V> { return base_; } constexpr V base() && { return std::move(base_); } constexpr const Pred& pred() const;constexpr iterator begin();constexpr auto end() { if constexpr (common_range<V>) return iterator{*this, ranges::end(base_)};else return sentinel{*this};} };template<class R, class Pred> filter_view(R&&, Pred) -> filter_view<views::all_t<R>, Pred>;}

constexpr explicit filter_view(V base, Pred pred);

Effects: Initializes base_ with std​::​move(base) and initializes_pred__ with std​::​move(pred).

constexpr const Pred& pred() const;

Effects: Equivalent to: return *pred_;

constexpr _iterator_ begin();

Preconditions: pred_.has_value() is true.

Returns: {*this, ranges​::​find_if(base_, ref(*pred_))}.

Remarks: In order to provide the amortized constant time complexity required by the range concept when filter_view models forward_range, this function caches the result within thefilter_view for use on subsequent calls.

25.7.8.3 Class filter_view​::​iterator [range.filter.iterator]

namespace std::ranges { template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class filter_view<V, Pred>::iterator { private: iterator_t<V> current_ = iterator_t<V>(); filter_view* parent_ = nullptr; public: using iterator_concept = see below;using iterator_category = see below; using value_type = range_value_t<V>;using difference_type = range_difference_t<V>;iterator() requires default_initializable<iterator_t<V>> = default;constexpr iterator(filter_view& parent, iterator_t<V> current);constexpr const iterator_t<V>& base() const & noexcept;constexpr iterator_t<V> base() &&;constexpr range_reference_t<V> operator*() const;constexpr iterator_t<V> operator->() const requires has-arrow<iterator_t<V>> && copyable<iterator_t<V>>;constexpr iterator& operator++();constexpr void operator++(int);constexpr iterator operator++(int) requires forward_range<V>;constexpr iterator& operator--() requires bidirectional_range<V>;constexpr iterator operator--(int) requires bidirectional_range<V>;friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<V>>;friend constexpr range_rvalue_reference_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 indirectly_swappable<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:

In that case,_iterator_​::​iterator_category is defined as follows:

constexpr _iterator_(filter_view& parent, iterator_t<V> current);

Effects: Initializes current_ with std​::​move(current) and_parent__ with addressof(parent).

constexpr const iterator_t<V>& base() const & noexcept;

Effects: Equivalent to: return current_;

constexpr iterator_t<V> base() &&;

Effects: Equivalent to: return std​::​move(current_);

constexpr range_reference_t<V> operator*() const;

Effects: Equivalent to: return *current_;

constexpr iterator_t<V> operator->() const requires [_has-arrow_](range.utility.helpers#concept:has-arrow "25.5.2 Helper concepts [range.utility.helpers]")<iterator_t<V>> && [copyable](concepts.object#concept:copyable "18.6 Object concepts [concepts.object]")<iterator_t<V>>;

Effects: Equivalent to: return current_;

constexpr _iterator_& operator++();

Effects: Equivalent to:current_ = ranges::find_if(std::move(++current_), ranges::end(_parent__->base_), ref(*_parent__->pred_));return *this;

constexpr void operator++(int);

Effects: Equivalent to ++*this.

Effects: Equivalent to:auto tmp = *this;++*this;return tmp;

Effects: Equivalent to:do --current_;while (!invoke(*_parent__->pred_, *current_));return *this;

Effects: Equivalent to:auto tmp = *this;--*this;return tmp;

friend constexpr bool operator==(const _iterator_& x, const _iterator_& y) requires [equality_comparable](concept.equalitycomparable#concept:equality%5Fcomparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<iterator_t<V>>;

Effects: Equivalent to: return x.current_ == y.current_;

friend constexpr range_rvalue_reference_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 [indirectly_swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_­swappable [alg.req.ind.swap]")<iterator_t<V>>;

Effects: Equivalent to ranges​::​iter_swap(x.current_, y.current_).

25.7.8.4 Class filter_view​::​sentinel [range.filter.sentinel]

namespace std::ranges { template<input_range V, indirect_unary_predicate<iterator_t<V>> Pred> requires view<V> && is_object_v<Pred> class filter_view<V, Pred>::sentinel { private: sentinel_t<V> end_ = sentinel_t<V>(); 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);};}

constexpr explicit _sentinel_(filter_view& parent);

Effects: Initializes end_ with ranges​::​end(parent.base_).

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_;