Shift Future::then and Future::thenMulti into the class definition
authorChristopher Dykes <cdykes@fb.com>
Wed, 28 Jun 2017 00:29:12 +0000 (17:29 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 28 Jun 2017 00:35:19 +0000 (17:35 -0700)
Summary:
GCC 7 has issues with `this->` in trailing return type declarations. This takes the approach of eliminating the trailing return types entirely.

Closes https://github.com/facebook/folly/pull/621

Reviewed By: yfeldblum

Differential Revision: D5324763

fbshipit-source-id: e38ae76c13ff60bc227146c1ec25afbac8b6982f

folly/futures/Future-inl.h
folly/futures/Future.h

index 2a8b56b888084e1b89175164d1430fab6ebfab75..09483c151e5c5658ae3cb8786956272a4319d02c 100644 (file)
@@ -297,18 +297,6 @@ Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
   });
 }
 
-template <class T>
-template <class Executor, class Arg, class... Args>
-auto Future<T>::then(Executor* x, Arg&& arg, Args&&... args)
-  -> decltype(this->then(std::forward<Arg>(arg),
-                         std::forward<Args>(args)...))
-{
-  auto oldX = getExecutor();
-  setExecutor(x);
-  return this->then(std::forward<Arg>(arg), std::forward<Args>(args)...).
-               via(oldX);
-}
-
 template <class T>
 Future<Unit> Future<T>::then() {
   return then([] () {});
@@ -1181,46 +1169,6 @@ Future<T> Future<T>::filter(F&& predicate) {
   });
 }
 
-template <class T>
-template <class Callback>
-auto Future<T>::thenMulti(Callback&& fn)
-    -> decltype(this->then(std::forward<Callback>(fn))) {
-  // thenMulti with one callback is just a then
-  return then(std::forward<Callback>(fn));
-}
-
-template <class T>
-template <class Callback, class... Callbacks>
-auto Future<T>::thenMulti(Callback&& fn, Callbacks&&... fns)
-    -> decltype(this->then(std::forward<Callback>(fn)).
-                      thenMulti(std::forward<Callbacks>(fns)...)) {
-  // thenMulti with two callbacks is just then(a).thenMulti(b, ...)
-  return then(std::forward<Callback>(fn)).
-         thenMulti(std::forward<Callbacks>(fns)...);
-}
-
-template <class T>
-template <class Callback, class... Callbacks>
-auto Future<T>::thenMultiWithExecutor(Executor* x, Callback&& fn,
-                                      Callbacks&&... fns)
-    -> decltype(this->then(std::forward<Callback>(fn)).
-                      thenMulti(std::forward<Callbacks>(fns)...)) {
-  // thenMultiExecutor with two callbacks is
-  // via(x).then(a).thenMulti(b, ...).via(oldX)
-  auto oldX = getExecutor();
-  setExecutor(x);
-  return then(std::forward<Callback>(fn)).
-         thenMulti(std::forward<Callbacks>(fns)...).via(oldX);
-}
-
-template <class T>
-template <class Callback>
-auto Future<T>::thenMultiWithExecutor(Executor* x, Callback&& fn)
-    -> decltype(this->then(std::forward<Callback>(fn))) {
-  // thenMulti with one callback is just a then with an executor
-  return then(x, std::forward<Callback>(fn));
-}
-
 template <class F>
 inline Future<Unit> when(bool p, F&& thunk) {
   return p ? std::forward<F>(thunk)().unit() : makeFuture();
index 2acc1b94cd85cff51b0dbb17c841a45fba6995a6..aaa4cb782ec9773a7c93fe1d5458d38d2661f60b 100644 (file)
@@ -210,9 +210,12 @@ class Future {
   /// In the former both b and c execute via x. In the latter, only b executes
   /// via x, and c executes via the same executor (if any) that f had.
   template <class Executor, class Arg, class... Args>
-  auto then(Executor* x, Arg&& arg, Args&&... args)
-    -> decltype(this->then(std::forward<Arg>(arg),
-                           std::forward<Args>(args)...));
+  auto then(Executor* x, Arg&& arg, Args&&... args) {
+    auto oldX = getExecutor();
+    setExecutor(x);
+    return this->then(std::forward<Arg>(arg), std::forward<Args>(args)...)
+        .via(oldX);
+  }
 
   /// Convenience method for ignoring the value and creating a Future<Unit>.
   /// Exceptions still propagate.
@@ -402,14 +405,17 @@ class Future {
   ///
   ///   f.thenMulti(a, b, c);
   template <class Callback, class... Callbacks>
-  auto thenMulti(Callback&& fn, Callbacks&&... fns)
-    -> decltype(this->then(std::forward<Callback>(fn)).
-                      thenMulti(std::forward<Callbacks>(fns)...));
+  auto thenMulti(Callback&& fn, Callbacks&&... fns) {
+    // thenMulti with two callbacks is just then(a).thenMulti(b, ...)
+    return then(std::forward<Callback>(fn))
+        .thenMulti(std::forward<Callbacks>(fns)...);
+  }
 
-  // Nothing to see here, just thenMulti's base case
   template <class Callback>
-  auto thenMulti(Callback&& fn)
-    -> decltype(this->then(std::forward<Callback>(fn)));
+  auto thenMulti(Callback&& fn) {
+    // thenMulti with one callback is just a then
+    return then(std::forward<Callback>(fn));
+  }
 
   /// Create a Future chain from a sequence of callbacks. i.e.
   ///
@@ -420,14 +426,21 @@ class Future {
   ///
   ///   f.thenMultiWithExecutor(executor, a, b, c);
   template <class Callback, class... Callbacks>
-  auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns)
-    -> decltype(this->then(std::forward<Callback>(fn)).
-                      thenMulti(std::forward<Callbacks>(fns)...));
+  auto thenMultiWithExecutor(Executor* x, Callback&& fn, Callbacks&&... fns) {
+    // thenMultiExecutor with two callbacks is
+    // via(x).then(a).thenMulti(b, ...).via(oldX)
+    auto oldX = getExecutor();
+    setExecutor(x);
+    return then(std::forward<Callback>(fn))
+        .thenMulti(std::forward<Callbacks>(fns)...)
+        .via(oldX);
+  }
 
-  // Nothing to see here, just thenMultiWithExecutor's base case
   template <class Callback>
-  auto thenMultiWithExecutor(Executor* x, Callback&& fn)
-    -> decltype(this->then(std::forward<Callback>(fn)));
+  auto thenMultiWithExecutor(Executor* x, Callback&& fn) {
+    // thenMulti with one callback is just a then with an executor
+    return then(x, std::forward<Callback>(fn));
+  }
 
   /// Discard a result, but propagate an exception.
   Future<Unit> unit() {