| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- #pragma once
- namespace stream { namespace detail {
- template <typename T>
- struct ref_or_val {
- ref_or_val operator=(T && val) { value = std::move(val); return *this; }
- operator T const &() const { return value; }
- T value;
- };
- template <typename T>
- struct ref_or_val<T&> {
- ref_or_val operator=(T & val) { value = &val; return *this; }
- operator T &() const { return *value; }
- T * value;
- };
- namespace filter {
- template <typename T>
- class iterator : public iterator_impl<T> {
- public:
- typedef iterator_impl<T> super;
- iterator(std::function<bool(T const&)> f, ::stream::iterator<T>&& impl, ::stream::iterator<T>&& end)
- : pred_(f)
- , impl_(std::forward<::stream::iterator<T>>(impl))
- , end_(std::forward<::stream::iterator<T>>(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<bool(T const&)> pred_;
- ref_or_val<T> mem_; // To avoid re-calcs, we store this
- ::stream::iterator<T> impl_, end_;
- };
- }
-
- template <typename T>
- class filter_stream : public stream_impl<T> {
- public:
- template <typename F>
- filter_stream(F&& func, stream_base<T> const& sb) : pred_(func), source_(sb) {}
- ~filter_stream() override {}
-
- iterator<T> begin() override {
- return {new filter::iterator<T>{pred_, source_.begin(), source_.end()}};
- }
-
- iterator<T> end() override {
- return {new filter::iterator<T>{pred_, source_.end(), source_.end()}};
- }
- private:
- std::function<bool(T const&)> pred_;
- stream_base<T> source_;
- };
-
- template <typename T>
- template <typename F>
- auto stream_base<T>::filter(F&& pred) const -> stream_base<T> {
- using impl_t = filter_stream<T>;
- return {std::make_shared<impl_t>(pred, *this)};
- }
- } }
|