Commit d8bc4210 authored by Hans Fugal's avatar Hans Fugal Committed by Sara Golemon

switch order of method/object in Future::then to match std::bind

Summary:
I have half a mind to just rip this out and let people use std::bind if they need this. But I won't be so cruel.

Why isn't this just implemented as `then(std::bind(method, object))` anyway? Is the template soup we have now faster?

Test Plan:
Fixed the unit tests to use the new format.
Will look to contbuild to catch all the things this might break (if anyone is using it at all?), and will fix them.

Reviewed By: hannesr@fb.com

Subscribers: trunkagent, exa, folly-diffs@, yfeldblum, jsedgwick, davejwatson

FB internal diff: D1831118

Signature: t1:1831118:1423243771:65db9a89daf14d8bd88331c503ba1ea7ab03b679
parent e1c576b4
...@@ -201,9 +201,9 @@ Future<T>::thenImplementation(F func, detail::argResult<isTry, F, Args...>) { ...@@ -201,9 +201,9 @@ Future<T>::thenImplementation(F func, detail::argResult<isTry, F, Args...>) {
} }
template <typename T> template <typename T>
template <typename Caller, typename R, typename... Args> template <typename R, typename Caller, typename... Args>
Future<typename isFuture<R>::Inner> Future<typename isFuture<R>::Inner>
Future<T>::then(Caller *instance, R(Caller::*func)(Args...)) { Future<T>::then(R(Caller::*func)(Args...), Caller *instance) {
typedef typename std::remove_cv< typedef typename std::remove_cv<
typename std::remove_reference< typename std::remove_reference<
typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg; typename detail::ArgType<Args...>::FirstArg>::type>::type FirstArg;
......
...@@ -299,14 +299,17 @@ class Future { ...@@ -299,14 +299,17 @@ class Future {
/// Variant where func is an member function /// Variant where func is an member function
/// ///
/// struct Worker { /// struct Worker { R doWork(Try<T>); }
/// R doWork(Try<T>&&); }
/// ///
/// Worker *w; /// Worker *w;
/// Future<R> f2 = f1.then(w, &Worker::doWork); /// Future<R> f2 = f1.then(&Worker::doWork, w);
template <typename Caller, typename R, typename... Args> ///
Future<typename isFuture<R>::Inner> /// This is just sugar for
then(Caller *instance, R(Caller::*func)(Args...)); ///
/// f1.then(std::bind(&Worker::doWork, w));
template <typename R, typename Caller, typename... Args>
Future<typename isFuture<R>::Inner>
then(R(Caller::*func)(Args...), Caller *instance);
/// Convenience method for ignoring the value and creating a Future<void>. /// Convenience method for ignoring the value and creating a Future<void>.
/// Exceptions still propagate. /// Exceptions still propagate.
......
...@@ -378,7 +378,7 @@ TEST(Future, thenFunction) { ...@@ -378,7 +378,7 @@ TEST(Future, thenFunction) {
auto f = makeFuture<string>("start") auto f = makeFuture<string>("start")
.then(doWorkStatic) .then(doWorkStatic)
.then(Worker::doWorkStatic) .then(Worker::doWorkStatic)
.then(&w, &Worker::doWork); .then(&Worker::doWork, &w);
EXPECT_EQ(f.value(), "start;static;class-static;class"); EXPECT_EQ(f.value(), "start;static;class-static;class");
} }
...@@ -400,7 +400,7 @@ TEST(Future, thenFunctionFuture) { ...@@ -400,7 +400,7 @@ TEST(Future, thenFunctionFuture) {
auto f = makeFuture<string>("start") auto f = makeFuture<string>("start")
.then(doWorkStaticFuture) .then(doWorkStaticFuture)
.then(Worker::doWorkStaticFuture) .then(Worker::doWorkStaticFuture)
.then(&w, &Worker::doWorkFuture); .then(&Worker::doWorkFuture, &w);
EXPECT_EQ(f.value(), "start;static;class-static;class"); EXPECT_EQ(f.value(), "start;static;class-static;class");
} }
......
...@@ -8,83 +8,83 @@ TEST(Future, thenVariants) { ...@@ -8,83 +8,83 @@ TEST(Future, thenVariants) {
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>&&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>&&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>&&>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>&&>());}
{Future<B> f = someFuture<A>().then([&](Try<A>&&){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](Try<A>&&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A> const&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A> const&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A> const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A> const&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, Try<A> const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A> const&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A> const&>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A> const&>());}
{Future<B> f = someFuture<A>().then([&](Try<A> const&){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](Try<A> const&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, Try<A>>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>>());}
{Future<B> f = someFuture<A>().then([&](Try<A>){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](Try<A>){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, Try<A>&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, Try<A>&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>&>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, Try<A>&>());}
{Future<B> f = someFuture<A>().then([&](Try<A>&){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](Try<A>&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, A&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A&&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A&&>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A&&>());}
{Future<B> f = someFuture<A>().then([&](A&&){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](A&&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A const&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A const&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A const&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, A const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A const&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A const&>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A const&>());}
{Future<B> f = someFuture<A>().then([&](A const&){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](A const&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, A>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A>());}
{Future<B> f = someFuture<A>().then([&](A){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](A){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&>);} {Future<B> f = someFuture<A>().then(&aFunction<Future<B>, A&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<Future<B>, A&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<Future<B>, A&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<Future<B>, A&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A&>());} {Future<B> f = someFuture<A>().then(aStdFunction<Future<B>, A&>());}
{Future<B> f = someFuture<A>().then([&](A&){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](A&){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then([&](){return someFuture<B>();});} {Future<B> f = someFuture<A>().then([&](){return someFuture<B>();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, Try<A>&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>&&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>&&>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>&&>());}
{Future<B> f = someFuture<A>().then([&](Try<A>&&){return B();});} {Future<B> f = someFuture<A>().then([&](Try<A>&&){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, Try<A> const&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, Try<A> const&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A> const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A> const&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, Try<A> const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A> const&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A> const&>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A> const&>());}
{Future<B> f = someFuture<A>().then([&](Try<A> const&){return B();});} {Future<B> f = someFuture<A>().then([&](Try<A> const&){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>>);} {Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, Try<A>>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>>());}
{Future<B> f = someFuture<A>().then([&](Try<A>){return B();});} {Future<B> f = someFuture<A>().then([&](Try<A>){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, Try<A>&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, Try<A>&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, Try<A>&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>&>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, Try<A>&>());}
{Future<B> f = someFuture<A>().then([&](Try<A>&){return B();});} {Future<B> f = someFuture<A>().then([&](Try<A>&){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, A&&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, A&&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, A&&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A&&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, A&&>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, A&&>());}
{Future<B> f = someFuture<A>().then([&](A&&){return B();});} {Future<B> f = someFuture<A>().then([&](A&&){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, A const&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, A const&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A const&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, A const&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A const&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, A const&>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, A const&>());}
{Future<B> f = someFuture<A>().then([&](A const&){return B();});} {Future<B> f = someFuture<A>().then([&](A const&){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, A>);} {Future<B> f = someFuture<A>().then(&aFunction<B, A>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, A>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, A>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, A>());}
{Future<B> f = someFuture<A>().then([&](A){return B();});} {Future<B> f = someFuture<A>().then([&](A){return B();});}
{Future<B> f = someFuture<A>().then(&aFunction<B, A&>);} {Future<B> f = someFuture<A>().then(&aFunction<B, A&>);}
{Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aStaticMethod<B, A&>);}
{Future<B> f = someFuture<A>().then(&anObject, &SomeClass::aMethod<B, A&>);} {Future<B> f = someFuture<A>().then(&SomeClass::aMethod<B, A&>, &anObject);}
{Future<B> f = someFuture<A>().then(aStdFunction<B, A&>());} {Future<B> f = someFuture<A>().then(aStdFunction<B, A&>());}
{Future<B> f = someFuture<A>().then([&](A&){return B();});} {Future<B> f = someFuture<A>().then([&](A&){return B();});}
{Future<B> f = someFuture<A>().then([&](){return B();});} {Future<B> f = someFuture<A>().then([&](){return B();});}
......
...@@ -114,7 +114,7 @@ TEST(Via, then_function) { ...@@ -114,7 +114,7 @@ TEST(Via, then_function) {
auto f = makeFuture(std::string("start")) auto f = makeFuture(std::string("start"))
.then(doWorkStatic) .then(doWorkStatic)
.then(Worker::doWorkStatic) .then(Worker::doWorkStatic)
.then(&w, &Worker::doWork) .then(&Worker::doWork, &w)
; ;
EXPECT_EQ(f.value(), "start;static;class-static;class"); EXPECT_EQ(f.value(), "start;static;class-static;class");
......
...@@ -50,8 +50,7 @@ tests = ( ...@@ -50,8 +50,7 @@ tests = (
[ [
["&aFunction<#{both}>"], ["&aFunction<#{both}>"],
["&SomeClass::aStaticMethod<#{both}>"], ["&SomeClass::aStaticMethod<#{both}>"],
# TODO switch these around (std::bind-style) ["&SomeClass::aMethod<#{both}>", "&anObject"],
["&anObject", "&SomeClass::aMethod<#{both}>"],
["aStdFunction<#{both}>()"], ["aStdFunction<#{both}>()"],
["[&](#{param}){return #{retval(ret)};}"], ["[&](#{param}){return #{retval(ret)};}"],
] ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment