streams.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #pragma once
  2. #include <memory>
  3. #include <algorithm>
  4. #define EQ_MEM(x) x == dynamic_cast<iterator const&>(other).x
  5. #define DELEGATE_ITERATOR_IMPL_BASE(impl) \
  6. super* clone() const override { return new iterator{*this}; } \
  7. bool operator==(super const&other) const override { return EQ_MEM(impl); } \
  8. #define DELEGATE_ITERATOR_IMPL(impl) \
  9. super& operator++() override { ++impl; return *this; } \
  10. DELEGATE_ITERATOR_IMPL_BASE(impl)
  11. namespace stream {
  12. template <typename T>
  13. class iterator {
  14. public:
  15. iterator(detail::iterator_impl<T>* impl) : impl_(impl) {}
  16. iterator(iterator const& other) : impl_(other.impl_->clone()) { }
  17. iterator(iterator&& other) : impl_(nullptr) { std::swap(impl_, other.impl_); }
  18. ~iterator() { if (impl_) delete impl_; }
  19. T operator*() const { return **impl_; }
  20. iterator& operator++() { ++(*impl_); return *this; }
  21. bool operator==(iterator const&other) const { return *impl_ == *(other.impl_); }
  22. bool operator!=(iterator const&other) const { return *impl_ != *(other.impl_); }
  23. private:
  24. detail::iterator_impl<T>* impl_;
  25. };
  26. namespace detail {
  27. template <typename T>
  28. stream_base<T, false> falsify(stream_base<T, true> const& in);
  29. template <typename T>
  30. class iterator_impl {
  31. public:
  32. virtual ~iterator_impl() {}
  33. virtual iterator_impl<T>* clone() const = 0;
  34. virtual T operator*() = 0;
  35. virtual iterator_impl<T>& operator++() = 0;
  36. virtual bool operator==(iterator_impl<T> const&other) const = 0;
  37. bool operator!=(iterator_impl<T> const&other) const {
  38. return !operator==(other);
  39. }
  40. };
  41. template <typename T>
  42. class stream_impl {
  43. public:
  44. virtual ~stream_impl() { }
  45. virtual ::stream::iterator<T> begin() = 0;
  46. virtual ::stream::iterator<T> end() = 0;
  47. };
  48. template <typename T, bool Own>
  49. class stream_base {
  50. private:
  51. template <typename F>
  52. using map_f = decltype(std::declval<F>()(std::declval<T>()));
  53. template <typename F>
  54. using flatmap_f = typename decltype(std::declval<F>()(std::declval<T>()))::value_type;
  55. using self = stream_base<T, Own>;
  56. public:
  57. stream_base(stream_impl<T>* impl) : impl_(impl) {}
  58. stream_base(stream_base&&other) : impl_(nullptr) { std::swap(impl_, other.impl_); }
  59. ~stream_base() { if (Own && impl_) delete impl_; }
  60. ::stream::iterator<T> begin() const { return impl_->begin(); }
  61. ::stream::iterator<T> end () const { return impl_->end (); }
  62. std::vector<T> collect() const {
  63. std::vector<T> coll;
  64. collect(coll);
  65. return coll;
  66. }
  67. template <typename C>
  68. C& collect(typename std::enable_if<!
  69. std::is_void<typename C::value_type>::value, C>::type& coll) const {
  70. std::copy(begin(), end(), std::inserter(coll.end(), coll));
  71. return coll;
  72. }
  73. template <typename F>
  74. T accumulate(F&& fold, T const& accum) {
  75. return std::accumulate(begin(), end(), accum, fold);
  76. }
  77. template <typename F>
  78. stream_base<map_f<F>, true> map(F&& func) const&;
  79. template <typename F>
  80. stream_base<map_f<F>, true> map(F&& func) &&;
  81. template <typename F>
  82. stream_base<T, true> filter(F&& func) const&;
  83. template <typename F>
  84. stream_base<T, true> filter(F&& func) &&;
  85. template <typename F>
  86. stream_base<flatmap_f<F>, true> flatmap(F&& func) const&;
  87. template <typename F>
  88. stream_base<flatmap_f<F>, true> flatmap(F&& func) &&;
  89. private:
  90. friend stream_base<T, false> falsify<T>(stream_base<T, true>const&);
  91. stream_impl<T>* impl_;
  92. };
  93. template <typename T>
  94. stream_base<T, false> const& falsify(stream_base<T, false> const& in) { return in; }
  95. template <typename T>
  96. stream_base<T, false> falsify(stream_base<T, true> const& in) {
  97. return stream_base<T, false>{in.impl_};
  98. }
  99. }
  100. }