filter.hpp 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #pragma once
  2. #include <iterator/filter_iterator.hpp>
  3. #include <stream/iterator.hpp>
  4. namespace stream::detail {
  5. template <typename T> class filter_iterator {
  6. public:
  7. filter_iterator(std::function<bool(T const &)> f, iterator<T> && impl,
  8. iterator<T> && end)
  9. : pred_(f), impl_(std::forward<iterator<T>>(impl)),
  10. end_(std::forward<iterator<T>>(end)) {
  11. advance();
  12. }
  13. T operator*() { return mem_; }
  14. filter_iterator & operator++() {
  15. ++impl_;
  16. advance();
  17. return *this;
  18. }
  19. bool operator==(filter_iterator const & rhs) const {
  20. return impl_ == rhs.impl_;
  21. }
  22. private:
  23. void advance() {
  24. while (impl_ != end_ && !pred_(mem_ = *impl_)) {
  25. ++impl_;
  26. }
  27. }
  28. std::function<bool(T const &)> pred_;
  29. ref_or_val<T> mem_; // To avoid re-calcs, we store this
  30. iterator<T> impl_, end_;
  31. };
  32. template <typename T> class filter_stream {
  33. public:
  34. template <typename F>
  35. filter_stream(F && func, stream_base<T> const & sb)
  36. : pred_(func), source_(sb) {}
  37. iterator<T> begin() { return ::iterator::filter_iterator(pred_, source_); }
  38. iterator<T> end() { return ::iterator::filter_iterator<iterator<T>>(); }
  39. private:
  40. typename ::iterator::filter_iterator<iterator<T>>::predicate_t pred_;
  41. stream_base<T> source_;
  42. };
  43. template <typename T>
  44. template <typename F>
  45. auto stream_base<T>::filter(F && pred) && -> stream_base<T> {
  46. return std::make_shared<filter_stream<T>>(pred, std::move(*this));
  47. }
  48. template <typename T>
  49. template <typename F>
  50. auto stream_base<T>::filter(F && pred) const & -> stream_base<T> {
  51. return std::make_shared<filter_stream<T>>(pred, *this);
  52. }
  53. }