transform_view.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. bool at_end() const { return super_t::impl().at_end(); }
  22. };
  23. template <typename S, typename Proj> class transform_view {
  24. private:
  25. private:
  26. S stream_;
  27. Proj projection_;
  28. public:
  29. transform_view(S && stream, Proj projection)
  30. : stream_(FWD(stream)), projection_(projection) {}
  31. auto begin() const { return transform_iterator(stream_.begin(), invoke()); }
  32. auto end() const {
  33. if constexpr (traits::is_sentinal_v<S>) {
  34. return stream_.end();
  35. } else {
  36. return transform_iterator(stream_.end(), invoke());
  37. }
  38. }
  39. bool empty() const { return stream_.empty(); }
  40. size_t size() const { return stream_.size(); }
  41. private:
  42. auto invoke() const {
  43. return std::function([this](traits::cref_t<S> t) -> decltype(auto) {
  44. return std::invoke(projection_, t);
  45. });
  46. }
  47. };
  48. template <typename S, typename Proj>
  49. transform_view(S &&, Proj) -> transform_view<S, Proj>;
  50. }
  51. MAKE_ITERATOR_FACADE_TYPEDEFS_T(stream::ranges::transform_iterator);
  52. namespace stream::ranges::views {
  53. template <typename Proj> class transform {
  54. public:
  55. transform(Proj const & projection) : projection_(projection) {}
  56. template <typename Stream>
  57. friend auto operator|(Stream && stream, transform map) {
  58. // TODO: if constexpr transform_view
  59. return transform_view(FWD(stream), std::move(map.projection_));
  60. }
  61. private:
  62. Proj projection_;
  63. };
  64. }
  65. #undef FWD