4-way overloads for SemiFuture::value
authorYedidya Feldblum <yfeldblum@fb.com>
Mon, 16 Oct 2017 17:56:48 +0000 (10:56 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 16 Oct 2017 18:05:52 +0000 (11:05 -0700)
Summary:
[Folly] 4-way overloads for `SemiFuture::value`.

Overload on the receiver reference category and `const`-qualification, deriving the return type reference category and `const`-qualification. Like `Optional`, `Try`, etc.

Differential Revision: D6062006

fbshipit-source-id: d7396cd4d4bb62e99445d5f61cb360898fa1c3f3

folly/futures/Future-inl.h
folly/futures/Future.h
folly/futures/test/SemiFutureTest.cpp

index 7a4f073fbd107ecde5dd6598539d56579f5a3c81..cdd38f7b2dbae5141f5222397c0be555092c31ee 100644 (file)
@@ -247,19 +247,33 @@ SemiFuture<T>::~SemiFuture() {
 }
 
 template <class T>
-typename std::add_lvalue_reference<T>::type SemiFuture<T>::value() {
+T& SemiFuture<T>::value() & {
   throwIfInvalid();
 
   return core_->getTry().value();
 }
 
 template <class T>
-typename std::add_lvalue_reference<const T>::type SemiFuture<T>::value() const {
+T const& SemiFuture<T>::value() const& {
   throwIfInvalid();
 
   return core_->getTry().value();
 }
 
+template <class T>
+T&& SemiFuture<T>::value() && {
+  throwIfInvalid();
+
+  return std::move(core_->getTry().value());
+}
+
+template <class T>
+T const&& SemiFuture<T>::value() const&& {
+  throwIfInvalid();
+
+  return std::move(core_->getTry().value());
+}
+
 template <class T>
 inline Future<T> SemiFuture<T>::via(Executor* executor, int8_t priority) && {
   throwIfInvalid();
index 5159062db21454b7e60889bbb31b98f3a69e6794..f5c3190f91ca9da03256037a59dacb8880ee08a6 100644 (file)
@@ -82,14 +82,19 @@ class SemiFuture {
 
   ~SemiFuture();
 
-  /** Return the reference to result. Should not be called if !isReady().
-    Will rethrow the exception if an exception has been
-    captured.
-    */
-  typename std::add_lvalue_reference<T>::type
-  value();
-  typename std::add_lvalue_reference<const T>::type
-  value() const;
+  /// Returns a reference to the result, with a reference category and const-
+  /// qualification equivalent to the reference category and const-qualification
+  /// of the receiver.
+  ///
+  /// If moved-from, throws NoState.
+  ///
+  /// If !isReady(), throws FutureNotReady.
+  ///
+  /// If an exception has been captured, throws that exception.
+  T& value() &;
+  T const& value() const&;
+  T&& value() &&;
+  T const&& value() const&&;
 
   /// Returns an inactive Future which will call back on the other side of
   /// executor (when it is activated).
index d3cb1a2667f60ca945975f9b6f11ecaf9b0c1128..64527adfc9ff7697876b034394030ef79cb9473f 100644 (file)
@@ -77,6 +77,11 @@ TEST(SemiFuture, value) {
   EXPECT_EQ(42, *up);
 
   EXPECT_THROW(makeSemiFuture<int>(eggs).value(), eggs_t);
+
+  EXPECT_TYPE(std::declval<SemiFuture<int>&>().value(), int&);
+  EXPECT_TYPE(std::declval<SemiFuture<int> const&>().value(), int const&);
+  EXPECT_TYPE(std::declval<SemiFuture<int>&&>().value(), int&&);
+  EXPECT_TYPE(std::declval<SemiFuture<int> const&&>().value(), int const&&);
 }
 
 TEST(SemiFuture, hasException) {