filter.hpp 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #pragma once
  2. namespace stream { namespace detail {
  3. namespace filter {
  4. template <typename T> class iterator {
  5. public:
  6. iterator(std::function<bool(T const &)> f, ::stream::iterator<T> && impl,
  7. ::stream::iterator<T> && end)
  8. : pred_(f), impl_(std::forward<::stream::iterator<T>>(impl)),
  9. end_(std::forward<::stream::iterator<T>>(end)) {
  10. advance();
  11. }
  12. T operator*() { return mem_; }
  13. iterator & operator++() {
  14. ++impl_;
  15. advance();
  16. return *this;
  17. }
  18. DELEGATE_ITERATOR_IMPL_BASE(impl_)
  19. private:
  20. void advance() {
  21. while (impl_ != end_ && !pred_(mem_ = *impl_)) {
  22. ++impl_;
  23. }
  24. }
  25. std::function<bool(T const &)> pred_;
  26. ref_or_val<T> mem_; // To avoid re-calcs, we store this
  27. ::stream::iterator<T> impl_, end_;
  28. };
  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. }}