/// \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 RANGES_DISABLE_WARNINGS 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 CPP_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_fn { private: friend view_access; template static constexpr auto bind(remove_if_fn remove_if, Pred pred) { return make_pipeable(bind_back(remove_if, std::move(pred))); } template static constexpr auto bind(remove_if_fn remove_if, Pred pred, Proj proj) { return make_pipeable( bind_back(remove_if, std::move(pred), std::move(proj))); } public: template constexpr auto operator()(Rng && rng, Pred pred) const -> CPP_ret(remove_if_view, Pred>)( // requires viewable_range && input_range && indirect_unary_predicate>) { return remove_if_view, Pred>{all(static_cast(rng)), std::move(pred)}; } template constexpr auto operator()(Rng && rng, Pred pred, Proj proj) const -> CPP_ret(remove_if_view, composed>)( // requires viewable_range && input_range && indirect_unary_predicate, Proj>>) { return remove_if_view, composed>{ all(static_cast(rng)), compose(std::move(pred), std::move(proj))}; } }; /// \relates remove_if_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view, remove_if) } // namespace views /// @} } // namespace ranges RANGES_RE_ENABLE_WARNINGS #include RANGES_SATISFY_BOOST_RANGE(::ranges::remove_if_view) #endif