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