Sam Jaffe пре 5 година
родитељ
комит
f4c63c428f
1 измењених фајлова са 13 додато и 12 уклоњено
  1. 13 12
      include/stream/either_stream.hpp

+ 13 - 12
include/stream/either_stream.hpp

@@ -17,9 +17,12 @@ namespace stream {
 }
 
 namespace stream::traits {
+  template <typename Either> struct either_traits {
+    static constexpr bool const is_either = false;
+  };
 
-  template <typename Either> struct either_traits;
   template <typename T, typename E> struct either_traits<::either<T, E>> {
+    static constexpr bool const is_either = true;
     using stream_type = either_stream<T, E>;
     using value_type = T;
     using error_type = E;
@@ -29,6 +32,8 @@ namespace stream::traits {
   using either_stream_t = typename either_traits<Either>::stream_type;
   template <typename Either>
   using either_value_t = typename either_traits<Either>::value_type;
+  template <typename Either>
+  inline constexpr bool is_either_v = either_traits<Either>::is_either;
 
 }
 
@@ -37,14 +42,7 @@ namespace stream {
   template <typename T, typename E> class either_stream {
   private:
     template <typename F, typename T2 = T>
-    using map_f = decltype(std::declval<F>()(std::declval<T2>()));
-
-    template <typename F, typename T2 = T>
-    using flatmap_f = traits::either_value_t<map_f<F, T2>>;
-
-    template <typename FT, typename FE>
-    inline static constexpr bool is_consumer_v =
-        std::is_void_v<map_f<FT, T>> && std::is_void_v<map_f<FE, E>>;
+    using result_of = decltype(std::declval<F>()(std::declval<T2>()));
 
   private:
     ::either<T, E> value_;
@@ -59,7 +57,9 @@ namespace stream {
     either_stream(::either<T, E> && v)
         : value_(std::forward<::either<T, E>>(v)) {}
 
-    template <typename F> either_stream<map_f<F>, E> map(F && fun) const {
+    template <typename F>
+    auto map(F && fun) const -> either_stream<result_of<F>, E> {
+      static_assert(!traits::is_either_v<result_of<F>>, "Cannot nest eithers");
       if (value_.index() == 0) {
         return fun(std::get<0>(value_));
       } else {
@@ -68,7 +68,8 @@ namespace stream {
     }
 
     template <typename F>
-    either_stream<flatmap_f<F>, E> flatmap(F && fun) const {
+    auto flatmap(F && fun) const
+        -> either_stream<traits::either_value_t<result_of<F>>, E> {
       if (value_.index() == 0) {
         return fun(std::get<0>(value_));
       } else {
@@ -78,7 +79,7 @@ namespace stream {
 
     template <typename FT, typename FE>
     auto match(FT && left, FE && right)
-        -> std::common_type_t<map_f<FT, T>, map_f<FE, E>> {
+        -> std::common_type_t<result_of<FT, T>, result_of<FE, E>> {
       if (value_.index() == 0) {
         return left(std::get<0>(value_));
       } else {