#pragma once namespace stream { namespace detail { namespace filter { template class iterator : public iterator_impl { public: typedef iterator_impl super; iterator(std::function f, ::stream::iterator&& impl, ::stream::iterator&& end) : pred_(f) , impl_(std::forward<::stream::iterator>(impl)) , end_(std::forward<::stream::iterator>(end)) { advance(); } ~iterator() {} T operator*() override { return mem_; } super& operator++() override { ++impl_; advance(); return *this; } DELEGATE_ITERATOR_IMPL_BASE(impl_) private: void advance() { while (impl_ != end_ && !pred_(mem_ = *impl_)) { ++impl_; } } std::function pred_; T mem_; // To avoid re-calcs, we store this ::stream::iterator impl_, end_; }; } template class filter_stream : public stream_impl { public: template filter_stream(F&& func, stream_base const& sb) : pred_(func), source_(sb) {} ~filter_stream() override {} iterator begin() override { return {new filter::iterator{pred_, source_.begin(), source_.end()}}; } iterator end() override { return {new filter::iterator{pred_, source_.end(), source_.end()}}; } private: std::function pred_; stream_base source_; }; template template auto stream_base::filter(F&& pred) const -> stream_base { using impl_t = filter_stream; return {std::make_shared(pred, *this)}; } } }