|
|
@@ -25,3 +25,65 @@ private:
|
|
|
It begin_, end_;
|
|
|
};
|
|
|
}
|
|
|
+
|
|
|
+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 <typename C>
|
|
|
+auto of(C && cont) -> detail::stream_base<decltype(*cont.begin())> {
|
|
|
+ return std::make_shared<detail::source_stream<C>>(std::forward<C>(cont));
|
|
|
+}
|
|
|
+
|
|
|
+template <typename T> detail::stream_base<T &> empty() {
|
|
|
+ return std::make_shared<detail::range_stream<T *>>(nullptr, nullptr);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Construct a single element stream containing the pointer given
|
|
|
+ */
|
|
|
+template <typename T> detail::stream_base<T &> of(T * ptr) {
|
|
|
+ return std::make_shared<detail::range_stream<T *>>(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 <typename It>
|
|
|
+detail::stream_base<typename It::reference> of(It begin, It end) {
|
|
|
+ return std::make_shared<detail::range_stream<It>>(begin, end);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Construct a stream given certain start and end bounds.
|
|
|
+ * e.g. stream::make_range_stream(0, 10)
|
|
|
+ */
|
|
|
+template <typename T> detail::stream_base<T &> range(T start, T const & end) {
|
|
|
+ std::vector<T> vec;
|
|
|
+ vec.reserve(end - start);
|
|
|
+ while (start < end) {
|
|
|
+ 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 <typename T>
|
|
|
+detail::stream_base<T &> range(T start, T const & end, T const & increment) {
|
|
|
+ int elems{(end - start) / increment};
|
|
|
+ if (elems < 0 || end == start) { return {}; }
|
|
|
+ std::vector<T> vec{start};
|
|
|
+ vec.reserve(elems + 1);
|
|
|
+ while (elems-- > 0) {
|
|
|
+ vec.emplace_back(start += increment);
|
|
|
+ }
|
|
|
+ return make_stream(std::move(vec));
|
|
|
+}
|
|
|
+}
|