transform_view.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #pragma once
  2. #include <functional>
  3. #include <iterator/proxy.h>
  4. #include <stream/detail/traits.h>
  5. #define FWD(x) std::forward<decltype(x)>(x)
  6. namespace stream::ranges {
  7. template <typename It, typename Proj>
  8. class transform_iterator : public proxy<It, transform_iterator<It, Proj>> {
  9. private:
  10. using super_t = proxy<It, transform_iterator<It, Proj>>;
  11. private:
  12. Proj projection_;
  13. public:
  14. transform_iterator() = default;
  15. transform_iterator(It iter, Proj projection)
  16. : super_t(std::move(iter)), projection_(projection) {}
  17. decltype(auto) dereference() const {
  18. return projection_(super_t::dereference());
  19. }
  20. };
  21. template <typename S, typename T> class transform_view {
  22. public:
  23. using Proj = std::function<T(traits::cref_t<S>)>;
  24. private:
  25. S stream_;
  26. Proj projection_;
  27. public:
  28. transform_view(S && stream, Proj projection)
  29. : stream_(FWD(stream)), projection_(projection) {}
  30. template <typename F>
  31. transform_view(S && stream, F projection)
  32. : stream_(FWD(stream)), projection_(projection) {}
  33. auto begin() const {
  34. return transform_iterator(stream_.begin(), projection_);
  35. }
  36. auto end() const { return transform_iterator(stream_.end(), projection_); }
  37. bool empty() const { return stream_.empty(); }
  38. size_t size() const { return stream_.size(); }
  39. };
  40. template <typename S, typename R, typename T>
  41. transform_view(S &&, std::function<R(T)>) -> transform_view<S, R>;
  42. template <typename S, typename F>
  43. transform_view(S &&, F)
  44. -> transform_view<S, std::invoke_result_t<F, traits::cref_t<S>>>;
  45. }
  46. MAKE_ITERATOR_FACADE_TYPEDEFS_T(stream::ranges::transform_iterator);
  47. namespace stream::ranges::views {
  48. template <typename Proj> class transform {
  49. public:
  50. transform(Proj const & projection) : projection_(projection) {}
  51. template <typename T, typename R>
  52. transform(R (*ptr)(T))
  53. : projection_([ptr](auto & t) -> R { return ptr(t); }) {}
  54. template <typename T, typename R>
  55. transform(R T::*ptr)
  56. : projection_([ptr](auto & t) -> R const & { return t.*ptr; }) {}
  57. template <typename T, typename R>
  58. transform(R (T::*ptr)() const)
  59. : projection_([ptr](auto & t) -> R { return (t.*ptr)(); }) {}
  60. template <typename T, typename R>
  61. transform(R (T::*ptr)() const noexcept)
  62. : projection_([ptr](auto & t) -> R { return (t.*ptr)(); }) {}
  63. template <typename Stream>
  64. friend auto operator|(Stream && stream, transform map) {
  65. // TODO: if constexpr transform_view
  66. return transform_view(FWD(stream), std::move(map.projection_));
  67. }
  68. private:
  69. Proj projection_;
  70. };
  71. template <typename Proj> transform(Proj const &) -> transform<Proj>;
  72. template <typename T, typename R>
  73. transform(R (*ptr)(T)) -> transform<std::function<R(T const &)>>;
  74. template <typename T, typename R>
  75. transform(R T::*ptr) -> transform<std::function<R const &(T const &)>>;
  76. template <typename T, typename R>
  77. transform(R (T::*ptr)() const) -> transform<std::function<R(T const &)>>;
  78. template <typename T, typename R>
  79. transform(R (T::*ptr)() const noexcept)
  80. -> transform<std::function<R(T const &)>>;
  81. }
  82. #undef FWD