|
|
@@ -15,10 +15,33 @@ super& operator++() override { ++impl; return *this; } \
|
|
|
DELEGATE_ITERATOR_IMPL_BASE(impl)
|
|
|
|
|
|
namespace stream {
|
|
|
+ namespace detail {
|
|
|
+ template <typename F> struct map_member_object;
|
|
|
+ template <typename T, typename R>
|
|
|
+ struct map_member_object<R T::*> {
|
|
|
+ using type = R const &;
|
|
|
+ type operator()(T const & val) const { return val.*mem; }
|
|
|
+ R T::*mem;
|
|
|
+ };
|
|
|
+ template <typename F> struct map_member_function;
|
|
|
+ template <typename T, typename R>
|
|
|
+ struct map_member_function<R (T::*)() const> {
|
|
|
+ using type = R;
|
|
|
+ type operator()(T const & val) const { return val.*mem(); }
|
|
|
+ R (T::* mem)() const;
|
|
|
+ };
|
|
|
+
|
|
|
+ template <typename T, typename = void>
|
|
|
+ struct is_dereferencable : public std::false_type {};
|
|
|
+
|
|
|
+ template <typename T>
|
|
|
+ struct is_dereferencable<T, typename std::enable_if<!std::is_void<decltype(*std::declval<T>())>::value>::type> : public std::true_type {};
|
|
|
+ }
|
|
|
+
|
|
|
template <typename T>
|
|
|
class iterator {
|
|
|
public:
|
|
|
- using value_type = T;
|
|
|
+ using value_type = typename std::remove_reference<T>::type;
|
|
|
using reference = value_type &;
|
|
|
using pointer = value_type *;
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
@@ -58,8 +81,23 @@ namespace stream {
|
|
|
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 {
|
|
|
+ class stream_base : public stream_base_pointer_impl<T> {
|
|
|
private:
|
|
|
template <typename F>
|
|
|
using map_f = decltype(std::declval<F>()(std::declval<T>()));
|
|
|
@@ -67,13 +105,17 @@ namespace stream {
|
|
|
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 (); }
|
|
|
|
|
|
- std::vector<T> collect() const {
|
|
|
- std::vector<T> coll;
|
|
|
+ bool empty() const { return begin() == end(); }
|
|
|
+
|
|
|
+ std::vector<clean> collect() const {
|
|
|
+ std::vector<clean> coll;
|
|
|
collect(coll);
|
|
|
return coll;
|
|
|
}
|
|
|
@@ -85,13 +127,37 @@ namespace stream {
|
|
|
}
|
|
|
|
|
|
template <typename F>
|
|
|
- T accumulate(F&& fold, T const& accum) {
|
|
|
+ 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;
|
|
|
|