filter.hpp 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #pragma once
  2. namespace stream { namespace detail {
  3. namespace filter {
  4. template <typename T>
  5. class iterator {
  6. public:
  7. iterator(std::function<bool(T const&)> f, ::stream::iterator<T>&& impl, ::stream::iterator<T>&& end)
  8. : pred_(f)
  9. , impl_(std::forward<::stream::iterator<T>>(impl))
  10. , end_(std::forward<::stream::iterator<T>>(end)) {
  11. advance();
  12. }
  13. T operator*() { return mem_; }
  14. iterator& operator++() {
  15. ++impl_;
  16. advance();
  17. return *this;
  18. }
  19. DELEGATE_ITERATOR_IMPL_BASE(impl_)
  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. ::stream::iterator<T> impl_, end_;
  29. };
  30. }
  31. template <typename T>
  32. class filter_stream {
  33. public:
  34. template <typename F>
  35. filter_stream(F&& func, stream_base<T> const& sb) : pred_(func), source_(sb) {}
  36. iterator<T> begin() {
  37. return {filter::iterator<T>{pred_, source_.begin(), source_.end()}};
  38. }
  39. iterator<T> end() {
  40. return {filter::iterator<T>{pred_, source_.end(), source_.end()}};
  41. }
  42. private:
  43. std::function<bool(T const&)> pred_;
  44. stream_base<T> source_;
  45. };
  46. template <typename T>
  47. template <typename F>
  48. auto stream_base<T>::filter(F&& pred) && -> stream_base<T> {
  49. return std::make_shared<filter_stream<T>>(pred, std::move(*this));
  50. }
  51. template <typename T>
  52. template <typename F>
  53. auto stream_base<T>::filter(F&& pred) const & -> stream_base<T> {
  54. return std::make_shared<filter_stream<T>>(pred, *this);
  55. }
  56. } }