#pragma once #include #include "self_iterating_contianer.hpp" namespace stream { namespace detail { template class join_iterator { public: using reference = typename C::const_iterator::reference; public: join_iterator(iterator && f, iterator && l) : start_(std::move(f)), finish_(std::move(l)) { if (start_ != finish_) { current_ = *start_; advance(); } } reference operator*() { return *current_; } join_iterator & operator++() { ++current_; advance(); return *this; } bool operator==(join_iterator const & rhs) const { return start_ == rhs.start_; } private: void advance() { while (!current_ && start_ != finish_) { if (++start_ == finish_) { break; } current_ = *start_; } } iterator start_; iterator finish_; self_iterating_container current_; }; template class join_stream { public: using T = typename C::value_type; explicit join_stream(stream_base const & sb) : source_(sb) {} iterator begin() { return {join_iterator{source_.begin(), source_.end()}}; } 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)); } }}