Nuke Future<void> (folly/futures)
[folly.git] / folly / futures / Try.h
index 7234a96eec605cb13e902ea7c853a2f8cdacb47e..d06d5b6225b73e74e696aad711c3614cdf17a4d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include <folly/Memory.h>
 #include <folly/futures/Deprecated.h>
 #include <folly/futures/FutureException.h>
+#include <folly/futures/Unit.h>
 
 namespace folly {
 
@@ -34,8 +35,7 @@ namespace folly {
  * context. Exceptions are stored as exception_wrappers so that the user can
  * minimize rethrows if so desired.
  *
- * There is a specialization, Try<void>, which represents either success
- * or an exception.
+ * To represent success or a captured exception, use Try<Unit>
  */
 template <class T>
 class Try {
@@ -73,6 +73,12 @@ class Try {
    */
   explicit Try(T&& v) : contains_(Contains::VALUE), value_(std::move(v)) {}
 
+  /// Implicit conversion from Try<void> to Try<Unit>
+  template <class T2 = T>
+  /* implicit */
+  Try(typename std::enable_if<std::is_same<Unit, T2>::value,
+                              Try<void> const&>::type t);
+
   /*
    * Construct a Try with an exception_wrapper
    *
@@ -100,14 +106,14 @@ class Try {
   }
 
   // Move constructor
-  Try(Try<T>&& t);
+  Try(Try<T>&& t) noexcept;
   // Move assigner
-  Try& operator=(Try<T>&& t);
+  Try& operator=(Try<T>&& t) noexcept;
 
-  // Non-copyable
-  Try(const Try<T>& t) = delete;
-  // Non-copyable
-  Try& operator=(const Try<T>& t) = delete;
+  // Copy constructor
+  Try(const Try& t);
+  // Copy assigner
+  Try& operator=(const Try& t);
 
   ~Try();
 
@@ -183,6 +189,13 @@ class Try {
     return *e_;
   }
 
+  const exception_wrapper& exception() const {
+    if (UNLIKELY(!hasException())) {
+      throw FutureException("exception(): Try does not contain an exception");
+    }
+    return *e_;
+  }
+
   /*
    * If the Try contains an exception and it is of type Ex, execute func(Ex)
    *
@@ -198,6 +211,16 @@ class Try {
     return e_->with_exception<Ex>(std::move(func));
   }
 
+  template <bool isTry, typename R>
+  typename std::enable_if<isTry, R>::type get() {
+    return std::forward<R>(*this);
+  }
+
+  template <bool isTry, typename R>
+  typename std::enable_if<!isTry, R>::type get() {
+    return std::forward<R>(value());
+  }
+
  private:
   Contains contains_;
   union {
@@ -285,6 +308,13 @@ class Try<void> {
     return *e_;
   }
 
+  const exception_wrapper& exception() const {
+    if (UNLIKELY(!hasException())) {
+      throw FutureException("exception(): Try does not contain an exception");
+    }
+    return *e_;
+  }
+
   /*
    * If the Try contains an exception and it is of type Ex, execute func(Ex)
    *
@@ -300,6 +330,11 @@ class Try<void> {
     return e_->with_exception<Ex>(std::move(func));
   }
 
+  template <bool, typename R>
+  R get() {
+    return std::forward<R>(*this);
+  }
+
  private:
   bool hasValue_;
   std::unique_ptr<exception_wrapper> e_{nullptr};
@@ -331,10 +366,10 @@ template <typename F>
 typename std::enable_if<
   !std::is_same<typename std::result_of<F()>::type, void>::value,
   Try<typename std::result_of<F()>::type>>::type
-makeTryFunction(F&& f);
+makeTryWith(F&& f);
 
 /*
- * Specialization of makeTryFunction for void
+ * Specialization of makeTryWith for void return
  *
  * @param f a function to execute and capture the result of
  *
@@ -344,7 +379,7 @@ template <typename F>
 typename std::enable_if<
   std::is_same<typename std::result_of<F()>::type, void>::value,
   Try<void>>::type
-makeTryFunction(F&& f);
+makeTryWith(F&& f);
 
 } // folly