Horizon
adjacent_remove_if.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2013-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 
14 #ifndef RANGES_V3_VIEW_ADJACENT_REMOVE_IF_HPP
15 #define RANGES_V3_VIEW_ADJACENT_REMOVE_IF_HPP
16 
17 #include <utility>
18 
19 #include <meta/meta.hpp>
20 
21 #include <range/v3/range_fwd.hpp>
22 
26 #include <range/v3/utility/box.hpp>
29 #include <range/v3/utility/static_const.hpp>
31 #include <range/v3/view/view.hpp>
32 
33 #include <range/v3/detail/prologue.hpp>
34 
35 namespace ranges
36 {
39  template<typename Rng, typename Pred>
40  struct RANGES_EMPTY_BASES adjacent_remove_if_view
41  : view_adaptor<adjacent_remove_if_view<Rng, Pred>, Rng,
42  is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
43  , private box<semiregular_box_t<Pred>, adjacent_remove_if_view<Rng, Pred>>
44  {
45  adjacent_remove_if_view() = default;
46  constexpr adjacent_remove_if_view(Rng rng, Pred pred)
47  : adjacent_remove_if_view::view_adaptor{detail::move(rng)}
48  , adjacent_remove_if_view::box(detail::move(pred))
49  {}
50 
51  private:
52  friend range_access;
53 
54  struct adaptor : adaptor_base
55  {
56  private:
58 
59  public:
60  adaptor() = default;
61  constexpr adaptor(adjacent_remove_if_view * rng) noexcept
62  : rng_(rng)
63  {}
64  static constexpr iterator_t<Rng> begin(adjacent_remove_if_view & rng)
65  {
66  return *rng.begin_;
67  }
68  constexpr void next(iterator_t<Rng> & it) const
69  {
70  RANGES_ASSERT(it != ranges::end(rng_->base()));
71  rng_->satisfy_forward(++it);
72  }
73  CPP_member
74  constexpr auto prev(iterator_t<Rng> & it) const //
75  -> CPP_ret(void)(
76  requires bidirectional_range<Rng>)
77  {
78  rng_->satisfy_reverse(it);
79  }
80  void advance() = delete;
81  void distance_to() = delete;
82  };
83  constexpr adaptor begin_adaptor()
84  {
85  cache_begin();
86  return {this};
87  }
88  CPP_member
89  constexpr auto end_adaptor() //
90  -> CPP_ret(adaptor)(
91  requires common_range<Rng>)
92  {
93  if(bidirectional_range<Rng>)
94  cache_begin();
95  return {this};
96  }
97  CPP_member
98  constexpr auto end_adaptor() noexcept //
99  -> CPP_ret(adaptor_base)(
100  requires (!common_range<Rng>))
101  {
102  return {};
103  }
104 
105  constexpr void satisfy_forward(iterator_t<Rng> & it)
106  {
107  auto const last = ranges::end(this->base());
108  if(it == last)
109  return;
110  auto & pred = this->adjacent_remove_if_view::box::get();
111  for(auto nxt = it; ++nxt != last && invoke(pred, *it, *nxt); it = nxt)
112  ;
113  }
114  constexpr void satisfy_reverse(iterator_t<Rng> & it)
115  {
116  auto const & first = *begin_;
117  RANGES_ASSERT(it != first);
118  (void)first;
119  auto prv = it;
120  --it;
121  if(prv == ranges::end(this->base()))
122  {
123  return;
124  }
125  auto & pred = this->adjacent_remove_if_view::box::get();
126  for(; invoke(pred, *it, *prv); prv = it, --it)
127  RANGES_ASSERT(it != first);
128  }
129 
130  void cache_begin()
131  {
132  if(begin_)
133  return;
134  auto it = ranges::begin(this->base());
135  satisfy_forward(it);
136  begin_.emplace(std::move(it));
137  }
138 
139  detail::non_propagating_cache<iterator_t<Rng>> begin_;
140  };
141 
142 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
143  template(typename Rng, typename Fun)(
144  requires copy_constructible<Rng>)
145  adjacent_remove_if_view(Rng &&, Fun)
147 #endif
148 
149  namespace views
150  {
152  {
153  template(typename Rng, typename Pred)(
154  requires viewable_range<Rng> AND forward_range<Rng> AND
156  constexpr adjacent_remove_if_view<all_t<Rng>, Pred> //
157  operator()(Rng && rng, Pred pred) const
158  {
159  return {all(static_cast<Rng &&>(rng)), std::move(pred)};
160  }
161  };
162 
164  {
165  using adjacent_remove_if_base_fn::operator();
166 
167  template<typename Pred>
168  constexpr auto operator()(Pred pred) const
169  {
170  return make_view_closure(
171  bind_back(adjacent_remove_if_base_fn{}, std::move(pred)));
172  }
173  };
174 
177  RANGES_INLINE_VARIABLE(adjacent_remove_if_fn, adjacent_remove_if)
178  } // namespace views
180 } // namespace ranges
181 
182 #include <range/v3/detail/epilogue.hpp>
183 #include <range/v3/detail/satisfy_boost_range.hpp>
184 RANGES_SATISFY_BOOST_RANGE(::ranges::adjacent_remove_if_view)
185 
186 #endif
Definition: box.hpp:163
CPP_concept indirect_binary_predicate_
\concept indirect_binary_predicate_
Definition: concepts.hpp:651
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
defer< bind_back, Fn, Ts... > bind_back
Definition: meta.hpp:994
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
Tiny meta-programming library.
Definition: adaptor.hpp:110
Definition: adjacent_remove_if.hpp:44
Definition: adaptor.hpp:475
Definition: adjacent_remove_if.hpp:152
Definition: adjacent_remove_if.hpp:164