File indexing completed on 2025-01-18 10:09:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_VIEW_REMOVE_IF_HPP
0015 #define RANGES_V3_VIEW_REMOVE_IF_HPP
0016
0017 #include <type_traits>
0018 #include <utility>
0019
0020 #include <meta/meta.hpp>
0021
0022 #include <range/v3/range_fwd.hpp>
0023
0024 #include <range/v3/functional/bind_back.hpp>
0025 #include <range/v3/functional/compose.hpp>
0026 #include <range/v3/functional/invoke.hpp>
0027 #include <range/v3/range/access.hpp>
0028 #include <range/v3/range/concepts.hpp>
0029 #include <range/v3/range/traits.hpp>
0030 #include <range/v3/utility/box.hpp>
0031 #include <range/v3/utility/optional.hpp>
0032 #include <range/v3/utility/semiregular_box.hpp>
0033 #include <range/v3/utility/static_const.hpp>
0034 #include <range/v3/view/adaptor.hpp>
0035 #include <range/v3/view/view.hpp>
0036
0037 #include <range/v3/detail/prologue.hpp>
0038
0039 namespace ranges
0040 {
0041
0042
0043 template<typename Rng, typename Pred>
0044 struct RANGES_EMPTY_BASES remove_if_view
0045 : view_adaptor<remove_if_view<Rng, Pred>, Rng,
0046 is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
0047 , private box<semiregular_box_t<Pred>>
0048 {
0049 remove_if_view() = default;
0050 constexpr remove_if_view(Rng rng, Pred pred)
0051 : remove_if_view::view_adaptor{detail::move(rng)}
0052 , remove_if_view::box(detail::move(pred))
0053 {}
0054
0055 private:
0056 friend range_access;
0057
0058 struct adaptor : adaptor_base
0059 {
0060 adaptor() = default;
0061 constexpr adaptor(remove_if_view * rng) noexcept
0062 : rng_(rng)
0063 {}
0064 static constexpr iterator_t<Rng> begin(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 private:
0084 remove_if_view * rng_;
0085 };
0086 constexpr adaptor begin_adaptor()
0087 {
0088 cache_begin();
0089 return {this};
0090 }
0091 CPP_member
0092 constexpr auto end_adaptor() const noexcept
0093 -> CPP_ret(adaptor_base)(
0094 requires (!common_range<Rng>))
0095 {
0096 return {};
0097 }
0098 CPP_member
0099 constexpr auto end_adaptor()
0100 -> CPP_ret(adaptor)(
0101 requires common_range<Rng>)
0102 {
0103 if(bidirectional_range<Rng>)
0104 cache_begin();
0105 return {this};
0106 }
0107
0108 constexpr void satisfy_forward(iterator_t<Rng> & it)
0109 {
0110 auto const last = ranges::end(this->base());
0111 auto & pred = this->remove_if_view::box::get();
0112 while(it != last && invoke(pred, *it))
0113 ++it;
0114 }
0115 constexpr void satisfy_reverse(iterator_t<Rng> & it)
0116 {
0117 RANGES_ASSERT(begin_);
0118 auto const & first = *begin_;
0119 auto & pred = this->remove_if_view::box::get();
0120 do
0121 {
0122 RANGES_ASSERT(it != first);
0123 (void)first;
0124 --it;
0125 } while(invoke(pred, *it));
0126 }
0127
0128 constexpr void cache_begin()
0129 {
0130 if(begin_)
0131 return;
0132 auto it = ranges::begin(this->base());
0133 satisfy_forward(it);
0134 begin_.emplace(std::move(it));
0135 }
0136
0137 detail::non_propagating_cache<iterator_t<Rng>> begin_;
0138 };
0139
0140 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
0141 template(typename Rng, typename Pred)(
0142 requires copy_constructible<Pred>)
0143 remove_if_view(Rng &&, Pred)
0144 -> remove_if_view<views::all_t<Rng>, Pred>;
0145 #endif
0146
0147 namespace views
0148 {
0149
0150
0151 struct remove_if_base_fn
0152 {
0153 template(typename Rng, typename Pred)(
0154 requires viewable_range<Rng> AND input_range<Rng> AND
0155 indirect_unary_predicate<Pred, iterator_t<Rng>>)
0156 constexpr remove_if_view<all_t<Rng>, Pred> operator()(Rng && rng, Pred pred)
0157 const
0158 {
0159 return remove_if_view<all_t<Rng>, Pred>{all(static_cast<Rng &&>(rng)),
0160 std::move(pred)};
0161 }
0162 template(typename Rng, typename Pred, typename Proj)(
0163 requires viewable_range<Rng> AND input_range<Rng> AND
0164 indirect_unary_predicate<Pred, projected<iterator_t<Rng>, Proj>>)
0165 constexpr remove_if_view<all_t<Rng>, composed<Pred, Proj>>
0166 operator()(Rng && rng, Pred pred, Proj proj) const
0167 {
0168 return remove_if_view<all_t<Rng>, composed<Pred, Proj>>{
0169 all(static_cast<Rng &&>(rng)),
0170 compose(std::move(pred), std::move(proj))};
0171 }
0172 };
0173
0174 struct remove_if_bind_fn
0175 {
0176 template<typename Pred>
0177 constexpr auto operator()(Pred pred) const
0178 {
0179 return make_view_closure(bind_back(remove_if_base_fn{}, std::move(pred)));
0180 }
0181 template(typename Pred, typename Proj)(
0182 requires (!range<Pred>))
0183 constexpr auto operator()(Pred && pred, Proj proj) const
0184 {
0185 return make_view_closure(bind_back(
0186 remove_if_base_fn{}, static_cast<Pred &&>(pred), std::move(proj)));
0187 }
0188 };
0189
0190 struct RANGES_EMPTY_BASES remove_if_fn
0191 : remove_if_base_fn, remove_if_bind_fn
0192 {
0193 using remove_if_base_fn::operator();
0194 using remove_if_bind_fn::operator();
0195 };
0196
0197
0198
0199 RANGES_INLINE_VARIABLE(remove_if_fn, remove_if)
0200 }
0201
0202 }
0203
0204 #include <range/v3/detail/satisfy_boost_range.hpp>
0205 RANGES_SATISFY_BOOST_RANGE(::ranges::remove_if_view)
0206
0207 #include <range/v3/detail/epilogue.hpp>
0208
0209 #endif