/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_VIEW_REMOVE_IF_HPP #define RANGES_V3_VIEW_REMOVE_IF_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-views /// @{ template struct RANGES_EMPTY_BASES remove_if_view : view_adaptor, Rng, is_finite::value ? finite : range_cardinality::value> , private box> { remove_if_view() = default; constexpr remove_if_view(Rng rng, Pred pred) : remove_if_view::view_adaptor{detail::move(rng)} , remove_if_view::box(detail::move(pred)) {} private: friend range_access; struct adaptor : adaptor_base { adaptor() = default; constexpr adaptor(remove_if_view * rng) noexcept : rng_(rng) {} static constexpr iterator_t begin(remove_if_view & rng) { return *rng.begin_; } constexpr void next(iterator_t & it) const { RANGES_ASSERT(it != ranges::end(rng_->base())); rng_->satisfy_forward(++it); } CPP_member constexpr auto prev(iterator_t & it) const // -> CPP_ret(void)( requires bidirectional_range) { rng_->satisfy_reverse(it); } void advance() = delete; void distance_to() = delete; private: remove_if_view * rng_; }; constexpr adaptor begin_adaptor() { cache_begin(); return {this}; } CPP_member constexpr auto end_adaptor() const noexcept // -> CPP_ret(adaptor_base)( requires (!common_range)) { return {}; } CPP_member constexpr auto end_adaptor() // -> CPP_ret(adaptor)( requires common_range) { if(bidirectional_range) cache_begin(); return {this}; } constexpr void satisfy_forward(iterator_t & it) { auto const last = ranges::end(this->base()); auto & pred = this->remove_if_view::box::get(); while(it != last && invoke(pred, *it)) ++it; } constexpr void satisfy_reverse(iterator_t & it) { RANGES_ASSERT(begin_); auto const & first = *begin_; auto & pred = this->remove_if_view::box::get(); do { RANGES_ASSERT(it != first); (void)first; --it; } while(invoke(pred, *it)); } constexpr void cache_begin() { if(begin_) return; auto it = ranges::begin(this->base()); satisfy_forward(it); begin_.emplace(std::move(it)); } detail::non_propagating_cache> begin_; }; #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17 template(typename Rng, typename Pred)( requires copy_constructible) remove_if_view(Rng &&, Pred) -> remove_if_view, Pred>; #endif namespace views { /// Given a source range, unary predicate, and optional projection, /// present a view of the elements that do not satisfy the predicate. struct remove_if_base_fn { template(typename Rng, typename Pred)( requires viewable_range AND input_range AND indirect_unary_predicate>) constexpr remove_if_view, Pred> operator()(Rng && rng, Pred pred) const { return remove_if_view, Pred>{all(static_cast(rng)), std::move(pred)}; } template(typename Rng, typename Pred, typename Proj)( requires viewable_range AND input_range AND indirect_unary_predicate, Proj>>) constexpr remove_if_view, composed> // operator()(Rng && rng, Pred pred, Proj proj) const { return remove_if_view, composed>{ all(static_cast(rng)), compose(std::move(pred), std::move(proj))}; } }; struct remove_if_bind_fn { template constexpr auto operator()(Pred pred) const // TODO: underconstrained { return make_view_closure(bind_back(remove_if_base_fn{}, std::move(pred))); } template(typename Pred, typename Proj)( requires (!range)) // TODO: underconstrained constexpr auto operator()(Pred && pred, Proj proj) const { return make_view_closure(bind_back( remove_if_base_fn{}, static_cast(pred), std::move(proj))); } }; struct RANGES_EMPTY_BASES remove_if_fn : remove_if_base_fn, remove_if_bind_fn { using remove_if_base_fn::operator(); using remove_if_bind_fn::operator(); }; /// \relates remove_if_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(remove_if_fn, remove_if) } // namespace views /// @} } // namespace ranges #include RANGES_SATISFY_BOOST_RANGE(::ranges::remove_if_view) #include #endif