#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 { private: using impl_t = ::stream::iterator; using local_iterator = typename C::const_iterator; public: using reference = typename local_iterator::reference; public: iterator(impl_t && f, impl_t && l) : start_(std::move(f)), finish_(std::move(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; } reference 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(); } } impl_t start_, finish_; C mem_; local_iterator curr_, end_; }; } template class join_stream { public: using T = typename C::value_type; explicit join_stream(stream_base const & sb) : source_(sb) {} ::stream::iterator begin() { return {join::iterator{source_.begin(), source_.end()}}; } ::stream::iterator end() { return {join::iterator{source_.end(), source_.end()}}; } private: stream_base source_; }; template stream_base make_join(stream_base const & sb) { return std::make_shared>(sb); } template template stream_base> stream_base::flatmap(F && func) && { return make_join(std::move(*this).map(func)); } template template stream_base> stream_base::flatmap(F && func) const & { return make_join(map(func)); } }}