| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- #pragma once
- #include <algorithm>
- #include <memory>
- #include <numeric>
- #define EQ_MEM(x) x == dynamic_cast<iterator const&>(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 <typename T>
- class iterator {
- public:
- using value_type = typename std::remove_reference<T>::type;
- using reference = value_type &;
- using pointer = value_type *;
- using difference_type = std::ptrdiff_t;
- using iterator_category = std::forward_iterator_tag;
- public:
- iterator(detail::iterator_impl<T>* 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<T>* impl_;
- };
-
- namespace detail {
- template <typename T>
- class iterator_impl {
- public:
- virtual ~iterator_impl() {}
- virtual iterator_impl<T>* clone() const = 0;
- virtual T operator*() = 0;
- virtual iterator_impl<T>& operator++() = 0;
- virtual bool operator==(iterator_impl<T> const&other) const = 0;
- bool operator!=(iterator_impl<T> const&other) const {
- return !operator==(other);
- }
- };
-
- template <typename T>
- class stream_impl {
- public:
- virtual ~stream_impl() { }
- virtual ::stream::iterator<T> begin() = 0;
- virtual ::stream::iterator<T> end() = 0;
- };
-
- template <typename T, typename = void>
- class stream_base_pointer_impl {};
-
- template <typename T>
- class stream_base_pointer_impl<T, typename std::enable_if<detail::is_dereferencable<typename std::remove_reference<T>::type>::value>::type> {
- private:
- using self = stream_base<T>;
- using noref = typename std::remove_reference<T>::type;
- using element_type = typename std::pointer_traits<noref>::element_type;
- public:
- auto deref() const -> stream_base<element_type &> {
- return static_cast<stream_base<T> const *>(this)->map([](T const & p) -> element_type & { return *p; });
- }
- };
- template <typename T>
- class stream_base : public stream_base_pointer_impl<T> {
- private:
- template <typename F>
- using map_f = decltype(std::declval<F>()(std::declval<T>()));
- template <typename F>
- using flatmap_f = typename decltype(std::declval<F>()(std::declval<T>()))::value_type;
- using self = stream_base<T>;
- using noref = typename std::remove_reference<T>::type;
- using clean = typename std::decay<T>::type;
- public:
- stream_base(std::shared_ptr<stream_impl<T>> const & impl) : impl_(impl) {}
- ::stream::iterator<T> begin() const { return impl_->begin(); }
- ::stream::iterator<T> end () const { return impl_->end (); }
-
- bool empty() const { return begin() == end(); }
-
- std::vector<clean> collect() const {
- std::vector<clean> coll;
- collect(coll);
- return coll;
- }
-
- template <typename C, typename = typename std::enable_if<!std::is_void<typename C::value_type>::value, void>::type>
- C& collect(C & coll) const {
- std::copy(begin(), end(), std::inserter(coll, coll.end()));
- return coll;
- }
-
- template <typename F>
- clean accumulate(F&& fold, clean const& accum) {
- return std::accumulate(begin(), end(), accum, fold);
- }
-
- clean accumulate(clean const& accum) {
- return std::accumulate(begin(), end(), accum);
- }
-
- template <typename F>
- void each(F && consumer) {
- std::for_each(begin(), end(), consumer);
- }
-
- template <typename F>
- stream_base<map_f<F>> map(F&& func) const;
- template <typename F, typename = typename std::enable_if<std::is_member_object_pointer<F>::value>::type>
- auto map(F && memvar) const -> stream_base<typename map_member_object<F>::type> {
- return map(map_member_object<F>{memvar});
- }
- template <typename F, typename = typename std::enable_if<std::is_member_function_pointer<F>::value>::type>
- auto map(F && memvar) const -> stream_base<typename map_member_function<F>::type> {
- return map(map_member_function<F>{memvar});
- }
-
- template <typename Cast>
- auto cast() const -> stream_base<Cast const &> {
- return map([](T const & p) -> Cast const & { return p; });
- }
- template <typename F>
- stream_base<T> filter(F&& func) const;
-
- template <typename F>
- stream_base<flatmap_f<F>> flatmap(F&& func) const;
- private:
- std::shared_ptr<stream_impl<T>> impl_;
- };
- }
- }
|