#pragma once template stream::detail::stream_base operator|(stream::detail::stream_base const&s, stream::flatmap_t&& f) { return s.flatmap(f.func); } template stream::detail::stream_base operator|(stream::detail::stream_base &&s, stream::flatmap_t&& f) { return std::move(s).flatmap(f.func); } namespace stream { template struct flatmap_t { template explicit flatmap_t(F&& f) : func(f) {} std::function func; }; } namespace stream { namespace detail { template class join_stream : public stream_impl { public: using T = typename C::value_type; class iterator : public iterator_impl { public: typedef iterator_impl super; iterator(::stream::iterator&& f, ::stream::iterator&& l) : start_(std::forward<::stream::iterator>(f)) , finish_(std::forward<::stream::iterator>(l)) { if (start_ != finish_) { mem_ = *(start_); curr_ = mem_.begin(); end_ = mem_.end(); advance(); } } ~iterator() {} T operator*() override { return *curr_; } super& operator++() override { ++curr_; advance(); return *this; } DELEGATE_ITERATOR_IMPL_BASE(start_) private: void advance() { while (curr_ == end_ && start_ != finish_) { mem_ = *(++start_); curr_ = mem_.begin(); end_ = mem_.end(); } } ::stream::iterator start_, finish_; C mem_; typename C::iterator curr_, end_; }; explicit join_stream(stream_base const& sb) : source_(sb) {} explicit join_stream(stream_base && sb) : source_(std::forward>(sb)) { } ~join_stream() override {} ::stream::iterator begin() override { return new iterator{source_.begin(), source_.end()}; } ::stream::iterator end() override { return new iterator{source_.end(), source_.end()}; } private: stream_base source_; }; template auto join(stream_base const& sb) -> stream_base { using T = typename C::value_type; using impl_t = join_stream; return stream_base{new impl_t{falsify(sb)}}; } template auto join(stream_base && sb) -> stream_base { using T = typename C::value_type; using impl_t = join_stream; return stream_base{new impl_t(std::forward>(sb))}; } template template auto stream_base::flatmap(F&& func) const& -> stream_base, true> { return join((*this).map(func)); } template template auto stream_base::flatmap(F&& func) && -> stream_base, true> { return join(std::forward(*this).map(func)); } } }