streams.hpp 3.9 KB

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