transform_view.h 2.1 KB

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