File indexing completed on 2025-01-18 10:09:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_ADJACENT_REMOVE_IF_HPP
0015 #define RANGES_V3_VIEW_ADJACENT_REMOVE_IF_HPP
0016
0017 #include <utility>
0018
0019 #include <meta/meta.hpp>
0020
0021 #include <range/v3/range_fwd.hpp>
0022
0023 #include <range/v3/functional/bind_back.hpp>
0024 #include <range/v3/functional/invoke.hpp>
0025 #include <range/v3/range/access.hpp>
0026 #include <range/v3/utility/box.hpp>
0027 #include <range/v3/utility/optional.hpp>
0028 #include <range/v3/utility/semiregular_box.hpp>
0029 #include <range/v3/utility/static_const.hpp>
0030 #include <range/v3/view/adaptor.hpp>
0031 #include <range/v3/view/view.hpp>
0032
0033 #include <range/v3/detail/prologue.hpp>
0034
0035 namespace ranges
0036 {
0037
0038
0039 template<typename Rng, typename Pred>
0040 struct RANGES_EMPTY_BASES adjacent_remove_if_view
0041 : view_adaptor<adjacent_remove_if_view<Rng, Pred>, Rng,
0042 is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
0043 , private box<semiregular_box_t<Pred>, adjacent_remove_if_view<Rng, Pred>>
0044 {
0045 adjacent_remove_if_view() = default;
0046 constexpr adjacent_remove_if_view(Rng rng, Pred pred)
0047 : adjacent_remove_if_view::view_adaptor{detail::move(rng)}
0048 , adjacent_remove_if_view::box(detail::move(pred))
0049 {}
0050
0051 private:
0052 friend range_access;
0053
0054 struct adaptor : adaptor_base
0055 {
0056 private:
0057 adjacent_remove_if_view * rng_;
0058
0059 public:
0060 adaptor() = default;
0061 constexpr adaptor(adjacent_remove_if_view * rng) noexcept
0062 : rng_(rng)
0063 {}
0064 static constexpr iterator_t<Rng> begin(adjacent_remove_if_view & rng)
0065 {
0066 return *rng.begin_;
0067 }
0068 constexpr void next(iterator_t<Rng> & it) const
0069 {
0070 RANGES_ASSERT(it != ranges::end(rng_->base()));
0071 rng_->satisfy_forward(++it);
0072 }
0073 CPP_member
0074 constexpr auto prev(iterator_t<Rng> & it) const
0075 -> CPP_ret(void)(
0076 requires bidirectional_range<Rng>)
0077 {
0078 rng_->satisfy_reverse(it);
0079 }
0080 void advance() = delete;
0081 void distance_to() = delete;
0082 };
0083 constexpr adaptor begin_adaptor()
0084 {
0085 cache_begin();
0086 return {this};
0087 }
0088 CPP_member
0089 constexpr auto end_adaptor()
0090 -> CPP_ret(adaptor)(
0091 requires common_range<Rng>)
0092 {
0093 if(bidirectional_range<Rng>)
0094 cache_begin();
0095 return {this};
0096 }
0097 CPP_member
0098 constexpr auto end_adaptor() noexcept
0099 -> CPP_ret(adaptor_base)(
0100 requires (!common_range<Rng>))
0101 {
0102 return {};
0103 }
0104
0105 constexpr void satisfy_forward(iterator_t<Rng> & it)
0106 {
0107 auto const last = ranges::end(this->base());
0108 if(it == last)
0109 return;
0110 auto & pred = this->adjacent_remove_if_view::box::get();
0111 for(auto nxt = it; ++nxt != last && invoke(pred, *it, *nxt); it = nxt)
0112 ;
0113 }
0114 constexpr void satisfy_reverse(iterator_t<Rng> & it)
0115 {
0116 auto const & first = *begin_;
0117 RANGES_ASSERT(it != first);
0118 (void)first;
0119 auto prv = it;
0120 --it;
0121 if(prv == ranges::end(this->base()))
0122 {
0123 return;
0124 }
0125 auto & pred = this->adjacent_remove_if_view::box::get();
0126 for(; invoke(pred, *it, *prv); prv = it, --it)
0127 RANGES_ASSERT(it != first);
0128 }
0129
0130 void cache_begin()
0131 {
0132 if(begin_)
0133 return;
0134 auto it = ranges::begin(this->base());
0135 satisfy_forward(it);
0136 begin_.emplace(std::move(it));
0137 }
0138
0139 detail::non_propagating_cache<iterator_t<Rng>> begin_;
0140 };
0141
0142 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0143 template(typename Rng, typename Fun)(
0144 requires copy_constructible<Rng>)
0145 adjacent_remove_if_view(Rng &&, Fun)
0146 -> adjacent_remove_if_view<views::all_t<Rng>, Fun>;
0147 #endif
0148
0149 namespace views
0150 {
0151 struct adjacent_remove_if_base_fn
0152 {
0153 template(typename Rng, typename Pred)(
0154 requires viewable_range<Rng> AND forward_range<Rng> AND
0155 indirect_binary_predicate_<Pred, iterator_t<Rng>, iterator_t<Rng>>)
0156 constexpr adjacent_remove_if_view<all_t<Rng>, Pred>
0157 operator()(Rng && rng, Pred pred) const
0158 {
0159 return {all(static_cast<Rng &&>(rng)), std::move(pred)};
0160 }
0161 };
0162
0163 struct adjacent_remove_if_fn : adjacent_remove_if_base_fn
0164 {
0165 using adjacent_remove_if_base_fn::operator();
0166
0167 template<typename Pred>
0168 constexpr auto operator()(Pred pred) const
0169 {
0170 return make_view_closure(
0171 bind_back(adjacent_remove_if_base_fn{}, std::move(pred)));
0172 }
0173 };
0174
0175
0176
0177 RANGES_INLINE_VARIABLE(adjacent_remove_if_fn, adjacent_remove_if)
0178 }
0179
0180 }
0181
0182 #include <range/v3/detail/epilogue.hpp>
0183 #include <range/v3/detail/satisfy_boost_range.hpp>
0184 RANGES_SATISFY_BOOST_RANGE(::ranges::adjacent_remove_if_view)
0185
0186 #endif