stream_base.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #pragma once
  2. #include <algorithm>
  3. #include <memory>
  4. #include <numeric>
  5. #include <optional>
  6. #include <vector>
  7. #include "iterator.hpp"
  8. namespace stream::detail {
  9. template <typename T, typename = void> class stream_base_pointer_impl {};
  10. template <typename T>
  11. class stream_base_pointer_impl<
  12. T, std::enable_if_t<traits::is_dereferencable_v<T>>> {
  13. private:
  14. using self_t = stream_base<T>;
  15. using pointer = typename std::remove_reference<T>::type;
  16. using element_type = typename std::pointer_traits<pointer>::element_type;
  17. public:
  18. auto deref() const & -> stream_base<element_type &> {
  19. return static_cast<self_t const *>(this)->map(
  20. [](T const & p) -> element_type & { return *p; });
  21. }
  22. auto deref() && -> stream_base<element_type &> {
  23. return static_cast<self_t &&>(*this).map(
  24. [](T const & p) -> element_type & { return *p; });
  25. }
  26. };
  27. template <typename T> class stream_base : public stream_base_pointer_impl<T> {
  28. private:
  29. using value_type = typename std::decay<T>::type;
  30. public:
  31. template <typename Stream> stream_base(std::shared_ptr<Stream> && impl) {
  32. do_begin = [](std::shared_ptr<void> p) -> iterator<T> {
  33. return std::static_pointer_cast<Stream>(p)->begin();
  34. };
  35. do_end = [](std::shared_ptr<void> p) -> iterator<T> {
  36. return std::static_pointer_cast<Stream>(p)->end();
  37. };
  38. impl_ = std::static_pointer_cast<void>(impl);
  39. }
  40. ::stream::iterator<T> begin() const { return do_begin(impl_); }
  41. ::stream::iterator<T> end() const { return do_end(impl_); }
  42. bool empty() const { return begin() == end(); }
  43. std::vector<value_type> collect() const {
  44. std::vector<value_type> coll;
  45. collect(coll);
  46. return coll;
  47. }
  48. template <typename C, typename = std::enable_if_t<
  49. !std::is_void_v<typename C::value_type>>>
  50. C & collect(C & coll) const {
  51. std::copy(begin(), end(), std::inserter(coll, coll.end()));
  52. return coll;
  53. }
  54. std::optional<value_type> first() const {
  55. return begin() != end() ? std::optional(*begin()) : std::nullopt;
  56. }
  57. template <typename F> bool none(F && pred) const {
  58. return std::none_of(begin(), end(), pred);
  59. }
  60. template <typename F> bool all(F && pred) const {
  61. return std::all_of(begin(), end(), pred);
  62. }
  63. template <typename F> bool any(F && pred) const {
  64. return std::any_of(begin(), end(), pred);
  65. }
  66. template <typename F>
  67. value_type accumulate(F && fold, value_type const & accum) const {
  68. return std::accumulate(begin(), end(), accum, fold);
  69. }
  70. template <typename F, typename = std::enable_if_t<
  71. std::is_invocable_v<F, value_type, value_type>>>
  72. std::optional<value_type> accumulate(F && fold) const {
  73. if (empty()) { return std::nullopt; }
  74. value_type first = *begin();
  75. return std::accumulate(++begin(), end(), first, fold);
  76. }
  77. value_type accumulate(value_type const & accum) const {
  78. return std::accumulate(begin(), end(), accum);
  79. }
  80. template <typename F> void each(F && consumer) const {
  81. std::for_each(begin(), end(), consumer);
  82. }
  83. template <typename F>
  84. stream_base<traits::mapped_t<T, F>> map(F && func) const &;
  85. template <typename F> stream_base<T> filter(F && func) const &;
  86. template <typename F>
  87. stream_base<traits::fmapped_t<T, F>> flatmap(F && func) const &;
  88. auto keys() const & {
  89. return map([](auto & kv) -> decltype(auto) { return kv.first; });
  90. }
  91. auto values() const & {
  92. return map([](auto & kv) -> decltype(auto) { return kv.second; });
  93. }
  94. template <typename F> stream_base<traits::mapped_t<T, F>> map(F && func) &&;
  95. template <typename F> stream_base<T> filter(F && func) &&;
  96. template <typename F>
  97. stream_base<traits::fmapped_t<T, F>> flatmap(F && func) &&;
  98. template <typename Cast> stream_base<Cast const &> cast() const & {
  99. return map([](T const & p) -> Cast const & { return p; });
  100. }
  101. template <typename Cast> stream_base<Cast const &> cast() && {
  102. return std::move(*this).map([](T const & p) -> Cast const & { return p; });
  103. }
  104. template <typename F, typename = traits::is_memvar_t<F>>
  105. stream_base<traits::memvar_f<F>> map(F && memvar) const & {
  106. return map(map_member_object<F>{memvar});
  107. }
  108. template <typename F, typename = traits::is_memfun_t<F>>
  109. stream_base<traits::memfun_f<F>> map(F && memvar) const & {
  110. return map(map_member_function<F>{memvar});
  111. }
  112. template <typename F, typename = traits::is_memvar_t<F>>
  113. stream_base<traits::memvar_f<F>> map(F && memvar) && {
  114. return std::move(*this).map(map_member_object<F>{memvar});
  115. }
  116. template <typename F, typename = traits::is_memfun_t<F>>
  117. stream_base<traits::memfun_f<F>> map(F && memvar) && {
  118. return std::move(*this).map(map_member_function<F>{memvar});
  119. }
  120. private:
  121. iterator<T> (*do_begin)(std::shared_ptr<void>){nullptr};
  122. iterator<T> (*do_end)(std::shared_ptr<void>){nullptr};
  123. std::shared_ptr<void> impl_{nullptr};
  124. };
  125. }