[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:
- Otherwise, if V models forward_range, theniterator_concept denotes forward_iterator_tag.
- Otherwise, iterator_concept denotes input_iterator_tag.
In that case,_iterator_::iterator_category is defined as follows:
- Let C denote the typeiterator_traits<iterator_t<V>>::iterator_category.
- If C modelsderived_from<bidirectional_iterator_tag>, then iterator_category denotes bidirectional_iterator_tag.
- Otherwise, if C modelsderived_from<forward_iterator_tag>, then iterator_category denotes forward_iterator_tag.
- Otherwise, iterator_category denotes C.
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_;