#pragma once #include namespace stream { namespace detail { #define JOIN_CTOR( mod ) \ start_ = mod(other.start_); \ finish_ = mod(other.finish_); \ std::ptrdiff_t n = std::distance(other.mem_.cbegin(), other.curr_); \ mem_ = mod(other.mem_); \ curr_ = mem_.begin(); \ std::advance(curr_, n); \ end_ = mem_.end(); namespace join { template class iterator { public: 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(iterator const & other) { JOIN_CTOR( ) } iterator(iterator && other) { JOIN_CTOR( std::move ) } iterator & operator=(iterator const & other) { JOIN_CTOR( ) return *this; } iterator & operator=(iterator && other) { JOIN_CTOR( std::move ) return *this; } ~iterator() {} typename C::value_type operator*() { return *curr_; } iterator& operator++() { ++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::const_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 {join::iterator{source_.begin(), source_.end()}}; } ::stream::iterator end() override { return {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)); } } }