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