filter.hpp 1.7 KB

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