|
|
@@ -9,63 +9,52 @@
|
|
|
|
|
|
#include "../streams.hpp"
|
|
|
|
|
|
-#include <numeric>
|
|
|
-
|
|
|
-namespace stream {
|
|
|
- template <typename T, typename R>
|
|
|
- struct map {
|
|
|
- template <typename F>
|
|
|
- explicit map(F&& f) : func(f) {}
|
|
|
- std::function<R(const T&)> func;
|
|
|
- };
|
|
|
+namespace stream { namespace traits {
|
|
|
+ template <typename T, typename P>
|
|
|
+ using is_filter = std::is_same<bool, decltype(std::declval<P>()(std::declval<T>()))>;
|
|
|
|
|
|
- template <typename T, typename R>
|
|
|
- struct flatmap {
|
|
|
- template <typename F>
|
|
|
- explicit flatmap(F&& f) : func(f) {}
|
|
|
- std::function<R(const T&)> func;
|
|
|
- };
|
|
|
+ template <typename C, typename T, typename = void>
|
|
|
+ struct is_collection : public std::false_type {};
|
|
|
|
|
|
- template <typename T>
|
|
|
- struct filter {
|
|
|
- template <typename F>
|
|
|
- explicit filter(F&& f) : pred(f) {}
|
|
|
- std::function<bool(const T&)> pred;
|
|
|
- };
|
|
|
-
|
|
|
- template <typename L, typename R = L>
|
|
|
- struct fold_left {
|
|
|
- template <typename F>
|
|
|
- explicit fold_left(F&& f, L const & i = L()) : init(i), fold(f) {}
|
|
|
- L init;
|
|
|
- std::function<L(const L&, const R&)> fold;
|
|
|
- };
|
|
|
-}
|
|
|
+ template <typename C, typename T>
|
|
|
+ struct is_collection<C, T, typename std::enable_if<std::is_constructible<typename C::value_type, T>::value>::type> : public std::true_type {};
|
|
|
+} }
|
|
|
|
|
|
namespace stream { namespace detail {
|
|
|
- template <typename T, typename R>
|
|
|
- stream_base<R> operator|(stream_base<T> const&s, ::stream::map<typename std::decay<T>::type, R>&& f) {
|
|
|
- return s.map(f.func);
|
|
|
+ template <typename T, typename F>
|
|
|
+ auto operator||(stream_base<T> const&s, F && f) -> decltype(s.flatmap(f)) {
|
|
|
+ return s.flatmap(f);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T, typename F, typename = typename std::enable_if<!traits::is_filter<T, F>::value>::type>
|
|
|
+ auto operator|(stream_base<T> const&s, F && f) -> decltype(s.map(f)) {
|
|
|
+ return s.map(f);
|
|
|
}
|
|
|
|
|
|
- template <typename T, typename C>
|
|
|
- stream_base<typename C::value_type> operator|(stream_base<T> const&s, ::stream::flatmap<typename std::decay<T>::type, C>&& f) {
|
|
|
- return s.flatmap(f.func);
|
|
|
+ template <typename T, typename P, typename = typename std::enable_if<traits::is_filter<T, P>::value>::type>
|
|
|
+ stream_base<T> operator|(stream_base<T> const&s, P && f) {
|
|
|
+ return s.filter(f);
|
|
|
}
|
|
|
|
|
|
- template <typename T>
|
|
|
- stream_base<T> operator|(stream_base<T> const&s, ::stream::filter<typename std::decay<T>::type>&& f) {
|
|
|
- return s.filter(f.pred);
|
|
|
+ template <typename R>
|
|
|
+ R operator >(stream_base<R> const &s, R const & val) {
|
|
|
+ return s.accumulate(val);
|
|
|
}
|
|
|
|
|
|
- template <typename L, typename R>
|
|
|
- L operator >(stream_base<R> const &s, ::stream::fold_left<L, typename std::decay<R>::type> && f) {
|
|
|
- return std::accumulate(s.begin(), s.end(), f.init, f.fold);
|
|
|
+ template <typename L, typename R, typename F>
|
|
|
+ L operator >(stream_base<R> const &s, std::pair<L, F> const & pair) {
|
|
|
+ return s.accumulate(pair.second, pair.first);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T, typename F, typename = typename std::enable_if<!traits::is_collection<F, T>::value>::type>
|
|
|
+ typename std::decay<T>::type operator >(stream_base<T> const &s, F && f) {
|
|
|
+ return s.accumulate(f, typename std::decay<T>::type());
|
|
|
}
|
|
|
|
|
|
- template <typename T, typename C>
|
|
|
+ template <typename T, typename C, typename = typename std::enable_if<traits::is_collection<C, T>::value>::type>
|
|
|
C & operator >(stream_base<T> const & s, C & c) {
|
|
|
s.collect(c);
|
|
|
return c;
|
|
|
}
|
|
|
} }
|
|
|
+
|