BRICKS
Small, useful blocks of code, to build bigger things.
Loading...
Searching...
No Matches
filter.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <iterator>
4
5namespace bricks::detail {
6
7template <typename Range, typename UnaryPredicate>
8class filter_iter {
9 private:
10 typename Range::iterator iter_;
11 typename Range::iterator end_;
12 UnaryPredicate predicate_;
13
14 void advance()
15 {
16 while (iter_ != end_ && !predicate_(*iter_)) {
17 ++iter_;
18 }
19 }
20
21 public:
22 using difference_type = std::ptrdiff_t;
23 using value_type = typename Range::value_type;
24 using pointer = value_type*;
25 using reference = value_type&;
26 using iterator_category = std::forward_iterator_tag;
27
28 explicit filter_iter(typename Range::iterator iter, typename Range::iterator end,
29 UnaryPredicate predicate)
30 : iter_{iter}, end_{end}, predicate_{predicate}
31 {
32 advance();
33 }
34
35 auto operator++() -> filter_iter&
36 {
37 ++iter_;
38 advance();
39 return *this;
40 }
41
42 auto operator++(int) -> filter_iter
43 {
44 auto tmp = *this;
45 ++*this;
46 return tmp;
47 }
48
49 auto operator==(const filter_iter& other) const -> bool { return iter_ == other.iter_; }
50 auto operator!=(const filter_iter& other) const -> bool { return !(*this == other); }
51
52 auto operator*() const -> value_type& { return *iter_; }
53};
54
55template <typename Range, typename UnaryPredicate>
56class filterer {
57 private:
58 Range& range_;
59 UnaryPredicate predicate_;
60
61 public:
62 explicit filterer(Range& range, UnaryPredicate predicate) : range_{range}, predicate_{predicate}
63 {
64 }
65
66 auto begin() -> filter_iter<Range, UnaryPredicate>
67 {
68 return filter_iter<Range, UnaryPredicate>{std::begin(range_), std::end(range_), predicate_};
69 }
70 auto end() -> filter_iter<Range, UnaryPredicate>
71 {
72 return filter_iter<Range, UnaryPredicate>{std::end(range_), std::end(range_), predicate_};
73 }
74};
75
76} // namespace bricks::detail