filter_iterator.hpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. //
  2. // filter_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 6/17/17.
  6. //
  7. #pragma once
  8. #include "end_aware_iterator.hpp"
  9. namespace iterator {
  10. template <typename Iter>
  11. class filter_iterator : public end_aware_iterator<Iter> {
  12. private:
  13. using super = end_aware_iterator<Iter>;
  14. public:
  15. using value_type = typename super::value_type;
  16. using reference = typename super::reference;
  17. using pointer = typename super::pointer;
  18. using difference_type = typename super::difference_type;
  19. using iterator_category = typename super::iterator_category;
  20. public:
  21. filter_iterator() = default;
  22. template <typename... Args>
  23. filter_iterator(std::function<bool(value_type const &)> && p, Args &&... super_args)
  24. : super(std::forward<Args>(super_args)...)
  25. , pred(std::move(p)) {
  26. if (should_advance()) { advance(); }
  27. }
  28. filter_iterator & operator++() {
  29. advance();
  30. return *this;
  31. }
  32. filter_iterator operator++(int) {
  33. filter_iterator tmp{*this};
  34. operator++();
  35. return tmp;
  36. }
  37. private:
  38. bool should_advance() {
  39. return !super::done() && !pred(super::operator*());
  40. }
  41. void advance() {
  42. do { super::operator++(); } while (should_advance());
  43. }
  44. std::function<bool(value_type const &)> pred;
  45. };
  46. }
  47. template <typename Pred, typename Iter>
  48. iterator::filter_iterator<Iter> make_filter_iterator(Pred && p, Iter it, Iter end) { return {p, it, end}; }
  49. template <typename Pred, typename C>
  50. auto make_filter_iterator(Pred && p, C & collect) -> iterator::filter_iterator<decltype(std::begin(collect))> {
  51. return { p, std::begin(collect), std::end(collect) };
  52. }
  53. template <typename Pred, typename C>
  54. auto make_filter_iterator(Pred && p, C const & collect) -> iterator::filter_iterator<decltype(std::begin(collect))> {
  55. return { p, std::begin(collect), std::end(collect) };
  56. }