|
|
@@ -5,188 +5,166 @@
|
|
|
#include <numeric>
|
|
|
#include <vector>
|
|
|
|
|
|
-#define DELEGATE_ITERATOR_IMPL_BASE(impl) \
|
|
|
- bool operator==(iterator const&other) const { \
|
|
|
- return impl == other.impl; \
|
|
|
- }
|
|
|
-
|
|
|
-#define DELEGATE_ITERATOR_IMPL(impl) \
|
|
|
- DELEGATE_ITERATOR_IMPL_BASE(impl) \
|
|
|
- iterator& operator++() { \
|
|
|
- ++impl; \
|
|
|
- return *this; \
|
|
|
- }
|
|
|
+#include "detail/ifd_pointer.hpp"
|
|
|
|
|
|
namespace stream {
|
|
|
-#define STREAM_ITERATOR_COPY() \
|
|
|
- copy(other.copy), dereference(other.dereference), compare(other.compare), destroy(other.destroy), advance(other.advance), type_(other.type_)
|
|
|
-
|
|
|
- template <typename T>
|
|
|
- class iterator {
|
|
|
+ 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;
|
|
|
+
|
|
|
+ private:
|
|
|
+ T (*dereference)(void *){nullptr};
|
|
|
+ bool (*compare)(void *, void *){nullptr};
|
|
|
+ void (*advance)(void *){nullptr};
|
|
|
+ char const * type_{nullptr};
|
|
|
+ detail::ifd_pointer impl_{};
|
|
|
+
|
|
|
public:
|
|
|
iterator() = default;
|
|
|
-
|
|
|
+
|
|
|
template <typename Iter>
|
|
|
- iterator(Iter impl) {
|
|
|
- copy = [](void * p) { return (void*) new Iter(*(Iter*)(p)); };
|
|
|
- dereference = [](void * p) -> T { return **((Iter*)p); };
|
|
|
- compare = [](void * l, void * r) { return *((Iter*)l) == *((Iter*)r); };
|
|
|
- destroy = [](void * p) { delete (Iter*)(p); };
|
|
|
- advance = [](void * p) { ++(*(Iter*)(p)); };
|
|
|
- type_ = typeid(Iter).name();
|
|
|
- impl_ = copy(&impl);
|
|
|
- }
|
|
|
-
|
|
|
- iterator(iterator const& other)
|
|
|
- : STREAM_ITERATOR_COPY()
|
|
|
- , impl_(copy(other.impl_)) {
|
|
|
- }
|
|
|
-
|
|
|
- iterator(iterator && other)
|
|
|
- : STREAM_ITERATOR_COPY()
|
|
|
- , impl_(other.impl_) {
|
|
|
- other.impl_ = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- iterator & operator=(iterator const & other) {
|
|
|
- return *this = iterator{other};
|
|
|
- }
|
|
|
+ iterator(Iter impl)
|
|
|
+ : dereference(&iterator::dereference_<Iter>),
|
|
|
+ compare(&iterator::compare_<Iter>),
|
|
|
+ advance(&iterator::advance_<Iter>), type_(typeid(Iter).name()),
|
|
|
+ impl_(std::forward<Iter>(impl)) {}
|
|
|
|
|
|
- iterator & operator=(iterator && other) {
|
|
|
- swap(*this, other);
|
|
|
+ T operator*() const { return dereference(impl_.get()); }
|
|
|
+ iterator & operator++() {
|
|
|
+ advance(impl_.get());
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
- ~iterator() { if (destroy) destroy(impl_); }
|
|
|
-
|
|
|
- T operator*() const { return dereference(impl_); }
|
|
|
- iterator& operator++() { advance(impl_); return *this; }
|
|
|
- bool operator==(iterator const&other) const {
|
|
|
+ bool operator==(iterator const & other) const {
|
|
|
if (strcmp(type_, other.type_)) { return false; }
|
|
|
- return compare(impl_, other.impl_);
|
|
|
+ return compare(impl_.get(), other.impl_.get());
|
|
|
}
|
|
|
- bool operator!=(iterator const&other) const {
|
|
|
+
|
|
|
+ bool operator!=(iterator const & other) const {
|
|
|
if (strcmp(type_, other.type_)) { return false; }
|
|
|
- return !compare(impl_, other.impl_);
|
|
|
+ return !compare(impl_.get(), other.impl_.get());
|
|
|
}
|
|
|
+
|
|
|
private:
|
|
|
friend void swap(iterator & lhs, iterator & rhs) {
|
|
|
using std::swap;
|
|
|
- swap(lhs.copy, rhs.copy);
|
|
|
swap(lhs.dereference, rhs.dereference);
|
|
|
swap(lhs.compare, rhs.compare);
|
|
|
- swap(lhs.destroy, rhs.destroy);
|
|
|
swap(lhs.advance, rhs.advance);
|
|
|
swap(lhs.type_, rhs.type_);
|
|
|
swap(lhs.impl_, rhs.impl_);
|
|
|
}
|
|
|
- using delegate = void(*)(void*);
|
|
|
- void* (*copy)(void*){nullptr};
|
|
|
- T (*dereference)(void*){nullptr};
|
|
|
- bool (*compare)(void*, void*){nullptr};
|
|
|
- delegate destroy{nullptr}, advance{nullptr};
|
|
|
- char const * type_{nullptr};
|
|
|
- void * impl_{nullptr};
|
|
|
+
|
|
|
+ template <typename It> static T dereference_(void * p) {
|
|
|
+ return **((It *)p);
|
|
|
+ }
|
|
|
+ template <typename It> static bool compare_(void * l, void * r) {
|
|
|
+ return *((It *)l) == *((It *)r);
|
|
|
+ }
|
|
|
+ template <typename It> static void advance_(void * p) { ++(*(It *)(p)); }
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
namespace detail {
|
|
|
- template <typename T, typename = void>
|
|
|
- class stream_base_pointer_impl {};
|
|
|
-
|
|
|
+ template <typename T, typename = void> class stream_base_pointer_impl {};
|
|
|
+
|
|
|
template <typename T>
|
|
|
- class stream_base_pointer_impl<T, typename std::enable_if<traits::is_dereferencable<T>::value>::type> {
|
|
|
+ class stream_base_pointer_impl<
|
|
|
+ T, typename std::enable_if<traits::is_dereferencable<T>::value>::type> {
|
|
|
private:
|
|
|
using self_t = stream_base<T>;
|
|
|
using pointer = typename std::remove_reference<T>::type;
|
|
|
using element_type = typename std::pointer_traits<pointer>::element_type;
|
|
|
+
|
|
|
public:
|
|
|
auto deref() const & -> stream_base<element_type &> {
|
|
|
- return static_cast<self_t const *>(this)->map([](T const & p) -> element_type & { return *p; });
|
|
|
+ return static_cast<self_t const *>(this)->map(
|
|
|
+ [](T const & p) -> element_type & { return *p; });
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
auto deref() && -> stream_base<element_type &> {
|
|
|
- return static_cast<self_t &&>(*this).map([](T const & p) -> element_type & { return *p; });
|
|
|
+ return static_cast<self_t &&>(*this).map(
|
|
|
+ [](T const & p) -> element_type & { return *p; });
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
+
|
|
|
template <typename T>
|
|
|
class stream_base : public stream_base_pointer_impl<T> {
|
|
|
private:
|
|
|
using value_type = typename std::decay<T>::type;
|
|
|
+
|
|
|
public:
|
|
|
- template <typename Stream>
|
|
|
- stream_base(std::shared_ptr<Stream> && impl) {
|
|
|
- do_begin = [](std::shared_ptr<void> p) -> iterator<T> { return std::static_pointer_cast<Stream>(p)->begin(); };
|
|
|
- do_end = [](std::shared_ptr<void> p) -> iterator<T> { return std::static_pointer_cast<Stream>(p)->end(); };
|
|
|
+ template <typename Stream> stream_base(std::shared_ptr<Stream> && impl) {
|
|
|
+ do_begin = [](std::shared_ptr<void> p) -> iterator<T> {
|
|
|
+ return std::static_pointer_cast<Stream>(p)->begin();
|
|
|
+ };
|
|
|
+ do_end = [](std::shared_ptr<void> p) -> iterator<T> {
|
|
|
+ return std::static_pointer_cast<Stream>(p)->end();
|
|
|
+ };
|
|
|
impl_ = std::static_pointer_cast<void>(impl);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
::stream::iterator<T> begin() const { return do_begin(impl_); }
|
|
|
- ::stream::iterator<T> end () const { return do_end (impl_); }
|
|
|
-
|
|
|
+ ::stream::iterator<T> end() const { return do_end(impl_); }
|
|
|
+
|
|
|
bool empty() const { return begin() == end(); }
|
|
|
-
|
|
|
+
|
|
|
std::vector<value_type> collect() const {
|
|
|
std::vector<value_type> coll;
|
|
|
collect(coll);
|
|
|
return coll;
|
|
|
}
|
|
|
-
|
|
|
- template <typename C, typename = typename std::enable_if<!std::is_void<typename C::value_type>::value, void>::type>
|
|
|
+
|
|
|
+ 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>
|
|
|
- value_type accumulate(F&& fold, value_type const& accum) const {
|
|
|
+ value_type accumulate(F && fold, value_type const & accum) const {
|
|
|
return std::accumulate(begin(), end(), accum, fold);
|
|
|
}
|
|
|
-
|
|
|
- value_type accumulate(value_type const& accum) const {
|
|
|
+
|
|
|
+ value_type accumulate(value_type const & accum) const {
|
|
|
return std::accumulate(begin(), end(), accum);
|
|
|
}
|
|
|
-
|
|
|
- template <typename F>
|
|
|
- void each(F && consumer) const {
|
|
|
+
|
|
|
+ template <typename F> void each(F && consumer) const {
|
|
|
std::for_each(begin(), end(), consumer);
|
|
|
}
|
|
|
-
|
|
|
- template <typename F>
|
|
|
- stream_base<traits::mapped_t<T, F>> map(F&& func) const &;
|
|
|
- template <typename F>
|
|
|
- stream_base<T> filter(F&& func) const &;
|
|
|
+
|
|
|
template <typename F>
|
|
|
- stream_base<traits::fmapped_t<T, F>> flatmap(F&& func) const &;
|
|
|
-
|
|
|
+ stream_base<traits::mapped_t<T, F>> map(F && func) const &;
|
|
|
+ template <typename F> stream_base<T> filter(F && func) const &;
|
|
|
template <typename F>
|
|
|
- stream_base<traits::mapped_t<T, F>> map(F&& func) &&;
|
|
|
+ stream_base<traits::fmapped_t<T, F>> flatmap(F && func) const &;
|
|
|
+
|
|
|
template <typename F>
|
|
|
- stream_base<T> filter(F&& func) &&;
|
|
|
+ stream_base<traits::mapped_t<T, F>> map(F && func) &&;
|
|
|
+ template <typename F> stream_base<T> filter(F && func) &&;
|
|
|
template <typename F>
|
|
|
- stream_base<traits::fmapped_t<T, F>> flatmap(F&& func) &&;
|
|
|
-
|
|
|
- template <typename Cast>
|
|
|
- stream_base<Cast const &> cast() const & {
|
|
|
+ stream_base<traits::fmapped_t<T, F>> flatmap(F && func) &&;
|
|
|
+
|
|
|
+ template <typename Cast> stream_base<Cast const &> cast() const & {
|
|
|
return map([](T const & p) -> Cast const & { return p; });
|
|
|
}
|
|
|
-
|
|
|
- template <typename Cast>
|
|
|
- stream_base<Cast const &> cast() && {
|
|
|
- return std::move(*this).map([](T const & p) -> Cast const & { return p; });
|
|
|
+
|
|
|
+ template <typename Cast> stream_base<Cast const &> cast() && {
|
|
|
+ return std::move(*this).map(
|
|
|
+ [](T const & p) -> Cast const & { return p; });
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
template <typename F, typename = traits::is_memvar_t<F>>
|
|
|
stream_base<traits::memvar_f<F>> map(F && memvar) const & {
|
|
|
return map(map_member_object<F>{memvar});
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
template <typename F, typename = traits::is_memfun_t<F>>
|
|
|
stream_base<traits::memfun_f<F>> map(F && memvar) const & {
|
|
|
return map(map_member_function<F>{memvar});
|
|
|
@@ -201,6 +179,7 @@ namespace stream {
|
|
|
stream_base<traits::memfun_f<F>> map(F && memvar) && {
|
|
|
return std::move(*this).map(map_member_function<F>{memvar});
|
|
|
}
|
|
|
+
|
|
|
private:
|
|
|
iterator<T> (*do_begin)(std::shared_ptr<void>){nullptr};
|
|
|
iterator<T> (*do_end)(std::shared_ptr<void>){nullptr};
|