#pragma once #include "source.hpp" namespace stream { /** * Construct a stream out of the given container. If C && is an rvalue reference, the returned object * will take ownership of cont. Otherwise, we capture cont by reference to maximise performance. */ template auto make_stream(C && cont) -> detail::stream_base { return std::make_shared>(std::forward(cont)); } /** * Construct a single element stream containing the pointer given */ template detail::stream_base make_stream(T * ptr) { return std::make_shared>(ptr, ptr + 1); } /** * Construct a stream from input iterators representing the start and end * Requirements: It must be an iterator type that provides the trait 'reference' */ template detail::stream_base make_stream(It begin, It end) { return std::make_shared>(begin, end); } /** * Construct a stream given certain start and end bounds. * e.g. stream::make_range_stream(0, 10) */ 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)); } /** * Construct a stream given certain start and end bounds, as well as an increment amount. * e.g. stream::make_range_stream(0, 10, 2) */ 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)); } }