Added rvalue and const rvalue overloads to Try
[folly.git] / folly / Try.h
index f38362b803c580ea0062a8616ae69dabf73a4b57..7b97754c7d13a632220da91101c8ddd413bd1e68 100644 (file)
@@ -114,15 +114,8 @@ class Try {
    */
   FOLLY_DEPRECATED("use Try(exception_wrapper)")
   explicit Try(std::exception_ptr ep)
-    : contains_(Contains::EXCEPTION) {
-    try {
-      std::rethrow_exception(ep);
-    } catch (std::exception& e) {
-      e_ = exception_wrapper(std::current_exception(), e);
-    } catch (...) {
-      e_ = exception_wrapper(std::current_exception());
-    }
-  }
+      : contains_(Contains::EXCEPTION),
+        e_(exception_wrapper::from_exception_ptr(ep)) {}
 
   // Move constructor
   Try(Try<T>&& t) noexcept;
@@ -142,21 +135,28 @@ class Try {
    *
    * @returns mutable reference to the contained value
    */
-  T& value()&;
+  T& value() &;
   /*
    * Get a rvalue reference to the contained value. If the Try contains an
    * exception it will be rethrown.
    *
    * @returns rvalue reference to the contained value
    */
-  T&& value()&&;
+  T&& value() &&;
   /*
    * Get a const reference to the contained value. If the Try contains an
    * exception it will be rethrown.
    *
    * @returns const reference to the contained value
    */
-  const T& value() const&;
+  const T& value() const &;
+  /*
+   * Get a const rvalue reference to the contained value. If the Try contains an
+   * exception it will be rethrown.
+   *
+   * @returns const rvalue reference to the contained value
+   */
+  const T&& value() const &&;
 
   /*
    * If the Try contains an exception, rethrow it. Otherwise do nothing.
@@ -169,13 +169,35 @@ class Try {
    *
    * @returns const reference to the contained value
    */
-  const T& operator*() const { return value(); }
+  const T& operator*() const & {
+    return value();
+  }
   /*
    * Dereference operator. If the Try contains an exception it will be rethrown.
    *
    * @returns mutable reference to the contained value
    */
-  T& operator*() { return value(); }
+  T& operator*() & {
+    return value();
+  }
+  /*
+   * Mutable rvalue dereference operator.  If the Try contains an exception it
+   * will be rethrown.
+   *
+   * @returns rvalue reference to the contained value
+   */
+  T&& operator*() && {
+    return std::move(value());
+  }
+  /*
+   * Const rvalue dereference operator.  If the Try contains an exception it
+   * will be rethrown.
+   *
+   * @returns rvalue reference to the contained value
+   */
+  const T&& operator*() const && {
+    return std::move(value());
+  }
 
   /*
    * Const arrow operator. If the Try contains an exception it will be
@@ -208,20 +230,34 @@ class Try {
     return hasException() && e_.is_compatible_with<Ex>();
   }
 
-  exception_wrapper& exception() {
+  exception_wrapper& exception() {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
-  const exception_wrapper& exception() const {
+  exception_wrapper&& exception() && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
+  const exception_wrapper& exception() const & {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
+  const exception_wrapper&& exception() const && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
   /*
    * @returns a pointer to the `std::exception` held by `*this`, if one is held;
    *          otherwise, returns `nullptr`.
@@ -339,15 +375,8 @@ class Try<void> {
    * @param ep The exception_pointer. Will be rethrown.
    */
   FOLLY_DEPRECATED("use Try(exception_wrapper)")
-  explicit Try(std::exception_ptr ep) : hasValue_(false) {
-    try {
-      std::rethrow_exception(ep);
-    } catch (const std::exception& e) {
-      e_ = exception_wrapper(std::current_exception(), e);
-    } catch (...) {
-      e_ = exception_wrapper(std::current_exception());
-    }
-  }
+  explicit Try(std::exception_ptr ep)
+      : hasValue_(false), e_(exception_wrapper::from_exception_ptr(ep)) {}
 
   // Copy assigner
   Try& operator=(const Try<void>& t) {
@@ -384,20 +413,34 @@ class Try<void> {
    *
    * @returns mutable reference to the exception contained by this Try
    */
-  exception_wrapper& exception() {
+  exception_wrapper& exception() {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
-  const exception_wrapper& exception() const {
+  exception_wrapper&& exception() && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
+  const exception_wrapper& exception() const & {
     if (!hasException()) {
       try_detail::throwTryDoesNotContainException();
     }
     return e_;
   }
 
+  const exception_wrapper&& exception() const && {
+    if (!hasException()) {
+      try_detail::throwTryDoesNotContainException();
+    }
+    return std::move(e_);
+  }
+
   /*
    * @returns a pointer to the `std::exception` held by `*this`, if one is held;
    *          otherwise, returns `nullptr`.
@@ -502,8 +545,14 @@ typename std::enable_if<
   Try<void>>::type
 makeTryWith(F&& f);
 
-template <typename... Ts>
-std::tuple<Ts...> unwrapTryTuple(std::tuple<folly::Try<Ts>...>&& ts);
+/**
+ * Tuple<Try<Type>...> -> std::tuple<Type...>
+ *
+ * Unwraps a tuple-like type containing a sequence of Try<Type> instances to
+ * std::tuple<Type>
+ */
+template <typename Tuple>
+auto unwrapTryTuple(Tuple&&);
 
 } // namespace folly