#pragma once namespace stream { namespace detail { namespace source { template class iterator { public: using value_type = typename std::iterator_traits::reference; explicit iterator(Iter it) : impl_(it) {} value_type operator*() { return *impl_; } DELEGATE_ITERATOR_IMPL(impl_) private: Iter impl_; }; template using reference = decltype(*std::declval().begin()); } template class source_stream { public: typedef source::reference reference; typedef decltype(std::declval().begin()) _iterator; explicit source_stream(C && cont) : source_(std::forward(cont)) {} iterator begin() { return {source::iterator<_iterator>{source_.begin()}}; } iterator end() { return {source::iterator<_iterator>{source_.end()}}; } private: C source_; }; template class range_stream { public: typedef V & reference; explicit range_stream(It b, It e) : begin_(b), end_(e) {} iterator begin() { return {source::iterator{begin_}}; } iterator end() { return {source::iterator{end_}}; } private: It begin_, end_; }; } template detail::stream_base> make_stream(C && cont) { return std::make_shared>(std::forward(cont)); } template detail::stream_base make_stream(T * ptr) { return std::make_shared>(ptr, ptr + 1); } template detail::stream_base make_stream(It begin, It end) { return std::make_shared>(begin, end); } template detail::stream_base make_range_stream(T start, T const & end) { std::vector vec; vec.reserve(end - start); while (end < start) { vec.emplace_back(start++); } return make_stream(std::move(vec)); } template detail::stream_base make_range_stream(T start, T const & end, T const & increment) { int elems{(end - start) / increment}; if (elems < 0 || end == start) { return {}; } std::vector vec{start}; vec.reserve(elems + 1); while (elems-- > 0) { vec.emplace_back(start += increment); } return make_stream(std::move(vec)); } }