Sam Jaffe 5 سال پیش
والد
کامیت
e1615cde92
1فایلهای تغییر یافته به همراه21 افزوده شده و 3 حذف شده
  1. 21 3
      include/stream/either_stream.hpp

+ 21 - 3
include/stream/either_stream.hpp

@@ -39,6 +39,21 @@ namespace stream::traits {
 
 namespace stream {
 
+  /**
+   * An either stream is an object that allows functional compositions on a type
+   * that is either a concrete value or an error-type. This can be used as an
+   * alternative to the "status and out-param" pattern or exception-throwing
+   * code. It combines the benefits of both types - gaining the immediate
+   * knowledge of error-information that is provided by the first, while also
+   * allowing you to avoid out-params.
+   * The weakness of this design is that it often requires remodeling your
+   * entire codebase to operate around the either_stream. In order to terminate
+   * the stream, a fail-fast option is provided with operator bool(). However,
+   * the primary intent is to chain together functions with map and flatmap
+   * until you either have the desired result, or an error. At that point, you
+   * invoke match and handle the error with a default return value, an
+   * error-handler callback, or a thrown exception.
+   */
   template <typename T, typename E> class either_stream {
   private:
     template <typename F, typename T2 = T>
@@ -57,10 +72,13 @@ namespace stream {
     either_stream(::either<T, E> && v)
         : value_(std::forward<::either<T, E>>(v)) {}
 
+    // This probably should be for internal use only
+    operator bool() const { return value_.index() == 0; }
+
     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) {
+      if (*this) {
         return fun(std::get<0>(value_));
       } else {
         return std::get<1>(value_);
@@ -70,7 +88,7 @@ namespace stream {
     template <typename F>
     auto flatmap(F && fun) const
         -> either_stream<traits::either_value_t<result_of<F>>, E> {
-      if (value_.index() == 0) {
+      if (*this) {
         return fun(std::get<0>(value_));
       } else {
         return std::get<1>(value_);
@@ -80,7 +98,7 @@ namespace stream {
     template <typename FT, typename FE>
     auto match(FT && left, FE && right)
         -> std::common_type_t<result_of<FT, T>, result_of<FE, E>> {
-      if (value_.index() == 0) {
+      if (*this) {
         return left(std::get<0>(value_));
       } else {
         return right(std::get<1>(value_));