transform_view.h 1.9 KB

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