#pragma once namespace stream { namespace detail { namespace join { template 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() {} typename C::value_type operator*() override { return *curr_; } super& operator++() override { ++curr_; advance(); return *this; } DELEGATE_ITERATOR_IMPL_BASE(start_) private: void advance() { while (curr_ == end_ && start_ != finish_) { if ( ++start_ == finish_ ) { break; } mem_ = *start_; curr_ = mem_.begin(); end_ = mem_.end(); } } ::stream::iterator start_, finish_; C mem_; typename C::iterator curr_, end_; }; } template class join_stream : public stream_impl { public: using T = typename C::value_type; explicit join_stream(stream_base const& sb) : source_(sb) {} ~join_stream() override {} ::stream::iterator begin() override { return {new join::iterator{source_.begin(), source_.end()}}; } ::stream::iterator end() override { return {new join::iterator{source_.end(), source_.end()}}; } private: stream_base source_; }; template auto make_join(stream_base const& sb) -> stream_base { using T = typename C::value_type; using impl_t = join_stream; return {std::make_shared(sb)}; } template template auto stream_base::flatmap(F&& func) const -> stream_base> { return make_join((*this).map(func)); } } }