#pragma once #include #include #include #define FWD(x) std::forward(x) namespace stream::ranges { template class transform_iterator : public proxy> { private: using super_t = proxy>; private: Proj projection_; public: transform_iterator() = default; transform_iterator(It iter, Proj projection) : super_t(std::move(iter)), projection_(projection) {} decltype(auto) dereference() const { return projection_(super_t::dereference()); } }; template class transform_view { public: using Proj = std::function)>; private: S stream_; Proj projection_; public: transform_view(S && stream, Proj projection) : stream_(FWD(stream)), projection_(projection) {} template transform_view(S && stream, F projection) : stream_(FWD(stream)), projection_(projection) {} auto begin() const { return transform_iterator(stream_.begin(), projection_); } auto end() const { return transform_iterator(stream_.end(), projection_); } bool empty() const { return stream_.empty(); } size_t size() const { return stream_.size(); } }; template transform_view(S &&, std::function) -> transform_view; template transform_view(S &&, F) -> transform_view>>; } MAKE_ITERATOR_FACADE_TYPEDEFS_T(stream::ranges::transform_iterator); namespace stream::ranges::views { template class transform { public: transform(Proj const & projection) : projection_(projection) {} template transform(R (*ptr)(T)) : projection_([ptr](auto & t) -> R { return ptr(t); }) {} template transform(R T::*ptr) : projection_([ptr](auto & t) -> R const & { return t.*ptr; }) {} template transform(R (T::*ptr)() const) : projection_([ptr](auto & t) -> R { return (t.*ptr)(); }) {} template transform(R (T::*ptr)() const noexcept) : projection_([ptr](auto & t) -> R { return (t.*ptr)(); }) {} template friend auto operator|(Stream && stream, transform map) { // TODO: if constexpr transform_view return transform_view(FWD(stream), std::move(map.projection_)); } private: Proj projection_; }; template transform(Proj const &) -> transform; template transform(R (*ptr)(T)) -> transform>; template transform(R T::*ptr) -> transform>; template transform(R (T::*ptr)() const) -> transform>; template transform(R (T::*ptr)() const noexcept) -> transform>; } #undef FWD