transform_view.h 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. auto empty() const {
  40. if constexpr (traits::has_empty_v<S>) {
  41. return stream_.empty();
  42. }
  43. }
  44. auto size() {
  45. if constexpr (traits::has_size_v<S>) {
  46. return stream_.size();
  47. }
  48. }
  49. private:
  50. auto invoke() const {
  51. return std::function([this](traits::cref_t<S> t) -> decltype(auto) {
  52. return std::invoke(projection_, t);
  53. });
  54. }
  55. };
  56. template <typename S, typename Proj>
  57. transform_view(S &&, Proj) -> transform_view<S, Proj>;
  58. }
  59. MAKE_ITERATOR_FACADE_TYPEDEFS_T(stream::ranges::transform_iterator);
  60. namespace stream::ranges::views {
  61. template <typename Proj> class transform {
  62. public:
  63. transform(Proj const & projection) : projection_(projection) {}
  64. template <typename Stream>
  65. friend auto operator|(Stream && stream, transform map) {
  66. // TODO: if constexpr transform_view
  67. return transform_view(FWD(stream), std::move(map.projection_));
  68. }
  69. private:
  70. Proj projection_;
  71. };
  72. }
  73. #undef FWD