#pragma once #include #include #include #define EQ_MEM(x) x == dynamic_cast(other).x #define DELEGATE_ITERATOR_IMPL_BASE(impl) \ super* clone() const override { return new iterator{*this}; } \ bool operator==(super const&other) const override { return EQ_MEM(impl); } \ #define DELEGATE_ITERATOR_IMPL(impl) \ super& operator++() override { ++impl; return *this; } \ DELEGATE_ITERATOR_IMPL_BASE(impl) namespace stream { template class iterator { public: explicit iterator(detail::iterator_impl* impl) : impl_(impl) {} iterator(iterator const& other) : impl_(other.impl_->clone()) { } iterator(iterator&& other) : impl_(nullptr) { std::swap(impl_, other.impl_); } ~iterator() { if (impl_) delete impl_; } T operator*() const { return **impl_; } iterator& operator++() { ++(*impl_); return *this; } bool operator==(iterator const&other) const { return *impl_ == *(other.impl_); } bool operator!=(iterator const&other) const { return *impl_ != *(other.impl_); } private: detail::iterator_impl* impl_; }; namespace detail { template stream_base falsify(stream_base const& in); template class iterator_impl { public: virtual ~iterator_impl() {} virtual iterator_impl* clone() const = 0; virtual T operator*() = 0; virtual iterator_impl& operator++() = 0; virtual bool operator==(iterator_impl const&other) const = 0; bool operator!=(iterator_impl const&other) const { return !operator==(other); } }; template class stream_impl { public: virtual ~stream_impl() { } virtual ::stream::iterator begin() = 0; virtual ::stream::iterator end() = 0; }; template class stream_base { private: template using map_f = decltype(std::declval()(std::declval())); template using flatmap_f = typename decltype(std::declval()(std::declval()))::value_type; using self = stream_base; public: explicit stream_base(stream_impl* impl) : impl_(impl) {} stream_base(stream_base&&other) : impl_(nullptr) { std::swap(impl_, other.impl_); } ~stream_base() { if (Own && impl_) delete impl_; } ::stream::iterator begin() const { return impl_->begin(); } ::stream::iterator end () const { return impl_->end (); } std::vector collect() const { std::vector coll; collect(coll); return coll; } template C& collect(typename std::enable_if::value, C>::type& coll) const { std::copy(begin(), end(), std::inserter(coll.end(), coll)); return coll; } template T accumulate(F&& fold, T const& accum) { return std::accumulate(begin(), end(), accum, fold); } template stream_base, true> map(F&& func) const&; template stream_base, true> map(F&& func) &&; template stream_base filter(F&& func) const&; template stream_base filter(F&& func) &&; template stream_base, true> flatmap(F&& func) const&; template stream_base, true> flatmap(F&& func) &&; private: friend stream_base falsify(stream_baseconst&); stream_impl* impl_; }; template stream_base const& falsify(stream_base const& in) { return in; } template stream_base falsify(stream_base const& in) { return stream_base{in.impl_}; } } }