A library for working with phylogenetic data.
v0.25.0
filter_iterator.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CONTAINERS_FILTER_ITERATOR_H_
2 #define GENESIS_UTILS_CONTAINERS_FILTER_ITERATOR_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2021 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
35 
36 #include <cstddef>
37 #include <iterator>
38 #include <type_traits>
39 
40 namespace genesis {
41 namespace utils {
42 
43 // =================================================================================================
44 // Filtering Iterator
45 // =================================================================================================
46 
57 template< typename PredicateFunctor, typename BaseIterator >
59 {
60 public:
61 
62  // -------------------------------------------------------------------------
63  // Member Types
64  // -------------------------------------------------------------------------
65 
66  using iterator_category = std::input_iterator_tag;
67 
68  using value_type = typename std::iterator_traits<BaseIterator>::value_type;
69  using reference = typename std::iterator_traits<BaseIterator>::reference;
70  using const_reference = typename std::iterator_traits<BaseIterator>::reference const;
71  using pointer = typename std::iterator_traits<BaseIterator>::pointer;
72  using difference_type = typename std::iterator_traits<BaseIterator>::difference_type;
73 
74  // -------------------------------------------------------------------------
75  // Constructor and Rule of Five
76  // -------------------------------------------------------------------------
77 
91  FilterIterator( PredicateFunctor unary_func, BaseIterator begin, BaseIterator end = BaseIterator{} )
92  : predicate_( unary_func )
93  , current_( begin )
94  , end_( end )
95  {
96  // Iterate to the first element that passes the filter.
97  while(( current_ != end_ ) && ( !predicate_( *current_ ))) {
98  ++current_;
99  }
100  }
101 
102  ~FilterIterator() = default;
103 
104  FilterIterator( FilterIterator const& ) = default;
105  FilterIterator( FilterIterator&& ) = default;
106 
107  FilterIterator& operator= ( FilterIterator const& ) = default;
108  FilterIterator& operator= ( FilterIterator&& ) = default;
109 
110  // Explicit copy constructor and assignment. Not needed.
111  // FilterIterator& operator=( FilterIterator const& input )
112  // {
113  // current_ = input.current_;
114  // return *this;
115  // }
116 
117  // -------------------------------------------------------------------------
118  // Basic Iterator Operators
119  // -------------------------------------------------------------------------
120 
122  {
123  return *current_;
124  }
125 
127  {
128  return *current_;
129  }
130 
132  {
133  return *current_;
134  }
135 
136  BaseIterator base() const
137  {
138  return current_;
139  }
140 
141  BaseIterator end() const
142  {
143  return end_;
144  }
145 
146  // -------------------------------------------------------------------------
147  // Iterator Navigation
148  // -------------------------------------------------------------------------
149 
151  {
152  advance_();
153  return *this;
154  }
155 
157  {
158  FilterIterator it(*this);
159  ++(*this);
160  return it;
161  }
162 
164  {
165  // Use the += operator to advance an iterator to the desired n.
166  auto copy = *this;
167  copy += n;
168  return copy;
169  }
170 
172  {
173  // Call advance for n many times, but check for premature ending.
174  for( difference_type i = 0; i < n; ++i ) {
175  advance_();
176  if( current_ == end_ ) {
177  break;
178  }
179  }
180  return *this;
181  }
182 
183  // -------------------------------------------------------------------------
184  // Iterator Interaction
185  // -------------------------------------------------------------------------
186 
188  {
189  // Use the + operator, which uses the += operator, to advance to the desired n.
190  return it + n;
191  }
192 
193  // -------------------------------------------------------------------------
194  // Iterator Comparison
195  // -------------------------------------------------------------------------
196 
197  bool operator==( FilterIterator const& it ) const
198  {
199  return current_ == it.current_;
200  }
201 
202  bool operator!=( FilterIterator const& it ) const
203  {
204  return !(*this == it);
205  }
206 
207  bool operator<( FilterIterator const& it ) const
208  {
209  return current_ - it.current_ < 0;
210  }
211 
212  bool operator>( FilterIterator const& it ) const
213  {
214  return it < *this;
215  }
216 
217  bool operator<=( FilterIterator const& it ) const
218  {
219  return !(*this > it);
220  }
221 
222  bool operator>=( FilterIterator const& it ) const
223  {
224  return !(*this < it);
225  }
226 
227  // -------------------------------------------------------------------------
228  // Internal Members
229  // -------------------------------------------------------------------------
230 
231 private:
232 
233  void advance_()
234  {
235  // Advance at least one element, and then until the filter passes.
236  do {
237  ++current_;
238  } while(( current_ != end_ ) && ( !predicate_( *current_ )));
239  }
240 
241  // -------------------------------------------------------------------------
242  // Internal Members
243  // -------------------------------------------------------------------------
244 
245 private:
246 
247  PredicateFunctor predicate_;
248 
249  BaseIterator current_;
250  BaseIterator end_;
251 
252 };
253 
254 // =================================================================================================
255 // Make Filtering Iterator
256 // =================================================================================================
257 
271 template<typename PredicateFunctor, typename BaseIterator>
273  PredicateFunctor unary_func,
274  BaseIterator begin,
275  BaseIterator end = BaseIterator{}
276 ) {
277  return FilterIterator<PredicateFunctor, BaseIterator>( unary_func, begin, end );
278 }
279 
284 template<typename PredicateFunctor, typename BaseIterator>
286  PredicateFunctor unary_func,
287  BaseIterator begin,
288  BaseIterator end
289 ) {
291  FilterIterator<PredicateFunctor, BaseIterator>( unary_func, begin, end ),
292  FilterIterator<PredicateFunctor, BaseIterator>( unary_func, end, end )
293  );
294 }
295 
300 template<typename PredicateFunctor, typename Container>
302  PredicateFunctor unary_func,
303  Container& container
304 ) {
307  unary_func, container.begin(), container.end()
308  ),
310  unary_func, container.end(), container.end()
311  )
312  );
313 }
314 
319 template<typename PredicateFunctor, typename Container>
321  PredicateFunctor unary_func,
322  Container const& container
323 ) {
326  unary_func, container.begin(), container.end()
327  ),
329  unary_func, container.end(), container.end()
330  )
331  );
332 }
333 
334 } // namespace utils
335 } // namespace genesis
336 
337 #endif // include guard
genesis::utils::FilterIterator::~FilterIterator
~FilterIterator()=default
genesis::utils::FilterIterator::base
BaseIterator base() const
Definition: filter_iterator.hpp:136
genesis::utils::FilterIterator::operator+
friend FilterIterator operator+(difference_type n, FilterIterator const &it)
Definition: filter_iterator.hpp:187
genesis::utils::FilterIterator::operator*
const_reference operator*() const
Definition: filter_iterator.hpp:126
genesis::utils::FilterIterator::operator<=
bool operator<=(FilterIterator const &it) const
Definition: filter_iterator.hpp:217
genesis::utils::FilterIterator
Iterator class that allows to filter an underlying iterator by skipping elements that do not satisfy ...
Definition: filter_iterator.hpp:58
range.hpp
genesis::utils::FilterIterator::operator+=
FilterIterator & operator+=(difference_type n)
Definition: filter_iterator.hpp:171
genesis::utils::FilterIterator::operator++
FilterIterator & operator++()
Definition: filter_iterator.hpp:150
genesis::utils::FilterIterator::reference
typename std::iterator_traits< BaseIterator >::reference reference
Definition: filter_iterator.hpp:69
genesis::utils::FilterIterator::value_type
typename std::iterator_traits< BaseIterator >::value_type value_type
Definition: filter_iterator.hpp:68
genesis::utils::FilterIterator::const_reference
typename std::iterator_traits< BaseIterator >::reference const const_reference
Definition: filter_iterator.hpp:70
genesis::utils::FilterIterator::operator<
bool operator<(FilterIterator const &it) const
Definition: filter_iterator.hpp:207
genesis::utils::FilterIterator::operator->
reference operator->() const
Definition: filter_iterator.hpp:131
genesis::utils::FilterIterator::operator>=
bool operator>=(FilterIterator const &it) const
Definition: filter_iterator.hpp:222
genesis::utils::Range
Simple wrapper for typical begin() and end() iterators, to be used in range-based for loops.
Definition: range.hpp:46
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::FilterIterator::end
BaseIterator end() const
Definition: filter_iterator.hpp:141
genesis::utils::FilterIterator::operator>
bool operator>(FilterIterator const &it) const
Definition: filter_iterator.hpp:212
genesis::utils::make_filter_range
Range< FilterIterator< PredicateFunctor, BaseIterator > > make_filter_range(PredicateFunctor unary_func, BaseIterator begin, BaseIterator end)
Construct a filtering range, given the filter predicate function as well as the underlying base itera...
Definition: filter_iterator.hpp:285
genesis::utils::FilterIterator::pointer
typename std::iterator_traits< BaseIterator >::pointer pointer
Definition: filter_iterator.hpp:71
genesis::utils::FilterIterator::operator+
FilterIterator operator+(difference_type n) const
Definition: filter_iterator.hpp:163
genesis::utils::FilterIterator::operator=
FilterIterator & operator=(FilterIterator const &)=default
genesis::utils::FilterIterator::operator!=
bool operator!=(FilterIterator const &it) const
Definition: filter_iterator.hpp:202
genesis::utils::FilterIterator::operator*
reference operator*()
Definition: filter_iterator.hpp:121
genesis::utils::FilterIterator::difference_type
typename std::iterator_traits< BaseIterator >::difference_type difference_type
Definition: filter_iterator.hpp:72
genesis::utils::make_filter_iterator
FilterIterator< PredicateFunctor, BaseIterator > make_filter_iterator(PredicateFunctor unary_func, BaseIterator begin, BaseIterator end=BaseIterator{})
Construct a filtering iterator, given the filter predicate function as well as the underlying base it...
Definition: filter_iterator.hpp:272
genesis::utils::FilterIterator::iterator_category
std::input_iterator_tag iterator_category
Definition: filter_iterator.hpp:66
genesis::utils::FilterIterator::operator++
FilterIterator operator++(int)
Definition: filter_iterator.hpp:156
genesis::utils::FilterIterator::operator==
bool operator==(FilterIterator const &it) const
Definition: filter_iterator.hpp:197
genesis::utils::FilterIterator::FilterIterator
FilterIterator(PredicateFunctor unary_func, BaseIterator begin, BaseIterator end=BaseIterator{})
Construct a filtering iterator, given the filter predicate function as well as the underlying base it...
Definition: filter_iterator.hpp:91