/// \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_ADJACENT_REMOVE_IF_HPP #define RANGES_V3_VIEW_ADJACENT_REMOVE_IF_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-views /// @{ template struct RANGES_EMPTY_BASES adjacent_remove_if_view : view_adaptor, Rng, is_finite::value ? finite : range_cardinality::value> , private box, adjacent_remove_if_view> { adjacent_remove_if_view() = default; constexpr adjacent_remove_if_view(Rng rng, Pred pred) : adjacent_remove_if_view::view_adaptor{detail::move(rng)} , adjacent_remove_if_view::box(detail::move(pred)) {} private: friend range_access; struct adaptor : adaptor_base { private: adjacent_remove_if_view * rng_; public: adaptor() = default; constexpr adaptor(adjacent_remove_if_view * rng) noexcept : rng_(rng) {} constexpr static iterator_t begin(adjacent_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; }; constexpr adaptor begin_adaptor() { cache_begin(); return {this}; } CPP_member constexpr auto end_adaptor() -> CPP_ret(adaptor)( // requires common_range) { if(bidirectional_range) cache_begin(); return {this}; } CPP_member constexpr auto end_adaptor() noexcept -> CPP_ret(adaptor_base)( // requires(!common_range)) { return {}; } constexpr void satisfy_forward(iterator_t & it) { auto const last = ranges::end(this->base()); if(it == last) return; auto & pred = this->adjacent_remove_if_view::box::get(); for(auto nxt = it; ++nxt != last && invoke(pred, *it, *nxt); it = nxt) ; } constexpr void satisfy_reverse(iterator_t & it) { auto const & first = *begin_; RANGES_ASSERT(it != first); (void)first; auto prv = it; --it; if(prv == ranges::end(this->base())) { return; } auto & pred = this->adjacent_remove_if_view::box::get(); for(; invoke(pred, *it, *prv); prv = it, --it) RANGES_ASSERT(it != first); } 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 Fun)(requires copy_constructible) adjacent_remove_if_view(Rng &&, Fun) ->adjacent_remove_if_view, Fun>; #endif namespace views { struct adjacent_remove_if_fn { private: friend view_access; template static constexpr auto bind(adjacent_remove_if_fn adjacent_remove_if, Pred pred) { return make_pipeable(bind_back(adjacent_remove_if, std::move(pred))); } public: template constexpr auto operator()(Rng && rng, Pred pred) const -> CPP_ret( adjacent_remove_if_view, Pred>)( // requires viewable_range && forward_range && indirect_binary_predicate_, iterator_t>) { return {all(static_cast(rng)), std::move(pred)}; } }; /// \relates adjacent_remove_if_fn /// \ingroup group-views RANGES_INLINE_VARIABLE(view, adjacent_remove_if) } // namespace views /// @} } // namespace ranges #include RANGES_SATISFY_BOOST_RANGE(::ranges::adjacent_remove_if_view) #endif