Horizon
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_REMOVE_IF_HPP
15 #define RANGES_V3_VIEW_REMOVE_IF_HPP
16 
17 #include <type_traits>
18 #include <utility>
19 
20 #include <meta/meta.hpp>
21 
22 #include <range/v3/range_fwd.hpp>
23 
30 #include <range/v3/utility/box.hpp>
33 #include <range/v3/utility/static_const.hpp>
35 #include <range/v3/view/view.hpp>
36 
37 #include <range/v3/detail/prologue.hpp>
38 
39 namespace ranges
40 {
43  template<typename Rng, typename Pred>
44  struct RANGES_EMPTY_BASES remove_if_view
45  : view_adaptor<remove_if_view<Rng, Pred>, Rng,
46  is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>
47  , private box<semiregular_box_t<Pred>>
48  {
49  remove_if_view() = default;
50  constexpr remove_if_view(Rng rng, Pred pred)
51  : remove_if_view::view_adaptor{detail::move(rng)}
52  , remove_if_view::box(detail::move(pred))
53  {}
54 
55  private:
56  friend range_access;
57 
58  struct adaptor : adaptor_base
59  {
60  adaptor() = default;
61  constexpr adaptor(remove_if_view * rng) noexcept
62  : rng_(rng)
63  {}
64  static constexpr iterator_t<Rng> begin(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  private:
84  remove_if_view * rng_;
85  };
86  constexpr adaptor begin_adaptor()
87  {
88  cache_begin();
89  return {this};
90  }
91  CPP_member
92  constexpr auto end_adaptor() const noexcept //
93  -> CPP_ret(adaptor_base)(
94  requires (!common_range<Rng>))
95  {
96  return {};
97  }
98  CPP_member
99  constexpr auto end_adaptor() //
100  -> CPP_ret(adaptor)(
101  requires common_range<Rng>)
102  {
103  if(bidirectional_range<Rng>)
104  cache_begin();
105  return {this};
106  }
107 
108  constexpr void satisfy_forward(iterator_t<Rng> & it)
109  {
110  auto const last = ranges::end(this->base());
111  auto & pred = this->remove_if_view::box::get();
112  while(it != last && invoke(pred, *it))
113  ++it;
114  }
115  constexpr void satisfy_reverse(iterator_t<Rng> & it)
116  {
117  RANGES_ASSERT(begin_);
118  auto const & first = *begin_;
119  auto & pred = this->remove_if_view::box::get();
120  do
121  {
122  RANGES_ASSERT(it != first);
123  (void)first;
124  --it;
125  } while(invoke(pred, *it));
126  }
127 
128  constexpr void cache_begin()
129  {
130  if(begin_)
131  return;
132  auto it = ranges::begin(this->base());
133  satisfy_forward(it);
134  begin_.emplace(std::move(it));
135  }
136 
137  detail::non_propagating_cache<iterator_t<Rng>> begin_;
138  };
139 
140 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
141  template(typename Rng, typename Pred)(
142  requires copy_constructible<Pred>)
143  remove_if_view(Rng &&, Pred)
145 #endif
146 
147  namespace views
148  {
152  {
153  template(typename Rng, typename Pred)(
154  requires viewable_range<Rng> AND input_range<Rng> AND
156  constexpr remove_if_view<all_t<Rng>, Pred> operator()(Rng && rng, Pred pred)
157  const
158  {
159  return remove_if_view<all_t<Rng>, Pred>{all(static_cast<Rng &&>(rng)),
160  std::move(pred)};
161  }
162  template(typename Rng, typename Pred, typename Proj)(
163  requires viewable_range<Rng> AND input_range<Rng> AND
164  indirect_unary_predicate<Pred, projected<iterator_t<Rng>, Proj>>)
166  operator()(Rng && rng, Pred pred, Proj proj) const
167  {
169  all(static_cast<Rng &&>(rng)),
170  compose(std::move(pred), std::move(proj))};
171  }
172  };
173 
175  {
176  template<typename Pred>
177  constexpr auto operator()(Pred pred) const // TODO: underconstrained
178  {
179  return make_view_closure(bind_back(remove_if_base_fn{}, std::move(pred)));
180  }
181  template(typename Pred, typename Proj)(
182  requires (!range<Pred>)) // TODO: underconstrained
183  constexpr auto operator()(Pred && pred, Proj proj) const
184  {
185  return make_view_closure(bind_back(
186  remove_if_base_fn{}, static_cast<Pred &&>(pred), std::move(proj)));
187  }
188  };
189 
190  struct RANGES_EMPTY_BASES remove_if_fn
192  {
193  using remove_if_base_fn::operator();
194  using remove_if_bind_fn::operator();
195  };
196 
200  } // namespace views
202 } // namespace ranges
203 
204 #include <range/v3/detail/satisfy_boost_range.hpp>
205 RANGES_SATISFY_BOOST_RANGE(::ranges::remove_if_view)
206 
207 #include <range/v3/detail/epilogue.hpp>
208 
209 #endif
Definition: box.hpp:163
CPP_concept indirect_unary_predicate
\concept indirect_unary_predicate
Definition: concepts.hpp:632
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: compose.hpp:33
Definition: remove_if.hpp:48
Definition: adaptor.hpp:475
Given a source range, unary predicate, and optional projection, present a view of the elements that d...
Definition: remove_if.hpp:152
Definition: remove_if.hpp:175
Definition: remove_if.hpp:192