Horizon
Loading...
Searching...
No Matches
remove_if.hpp
Go to the documentation of this file.
1
2// 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
23
33#include <range/v3/utility/static_const.hpp>
36
37#include <range/v3/detail/prologue.hpp>
38
39namespace 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)(
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 {
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 {
151 struct remove_if_base_fn
152 {
153 template(typename Rng, typename Pred)(
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>>)
165 constexpr remove_if_view<all_t<Rng>, composed<Pred, Proj>> //
166 operator()(Rng && rng, Pred pred, Proj proj) const
167 {
168 return remove_if_view<all_t<Rng>, composed<Pred, Proj>>{
169 all(static_cast<Rng &&>(rng)),
170 compose(std::move(pred), std::move(proj))};
171 }
172 };
173
174 struct remove_if_bind_fn
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
191 : remove_if_base_fn, remove_if_bind_fn
192 {
193 using remove_if_base_fn::operator();
194 using remove_if_bind_fn::operator();
195 };
196
199 RANGES_INLINE_VARIABLE(remove_if_fn, remove_if)
200 } // namespace views
202} // namespace ranges
203
204#include <range/v3/detail/satisfy_boost_range.hpp>
205RANGES_SATISFY_BOOST_RANGE(::ranges::remove_if_view)
206
207#include <range/v3/detail/epilogue.hpp>
208
209#endif
Definition box.hpp:163
The bidirectional_range concept.
The common_range concept.
The indirect_unary_predicate concept.
The input_range concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
defer< bind_back, Fn, Ts... > bind_back
Definition meta.hpp:994
Tiny meta-programming library.
Definition adaptor.hpp:110
Definition remove_if.hpp:48
Definition adaptor.hpp:475