#pragma once #include #include #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()); } bool at_end() const { return super_t::impl().at_end(); } }; template class transform_view { private: private: S stream_; Proj projection_; public: transform_view(S && stream, Proj projection) : stream_(FWD(stream)), projection_(projection) {} auto begin() const { return transform_iterator(stream_.begin(), invoke()); } auto end() const { if constexpr (detail::is_sentinal_v) { return stream_.end(); } else { return transform_iterator(stream_.end(), invoke()); } } SFINAE(detail::has_empty_v, bool) empty() const { return stream_.empty(); } SFINAE(detail::has_size_v, size_t) size() { return stream_.size(); } private: auto invoke() const { return std::function([this](detail::cref_t t) -> decltype(auto) { return std::invoke(projection_, t); }); } }; template transform_view(S &&, Proj) -> 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 friend auto operator|(Stream && stream, transform map) { // TODO: if constexpr transform_view return transform_view(FWD(stream), std::move(map.projection_)); } private: Proj projection_; }; } #undef FWD #include