Commit 4733fd1c authored by Hannes Roth's avatar Hannes Roth Committed by Dave Watson

(Wangle) Support .then(function pointer) syntax

Summary:
Support `.then(&static_function)`, `.then(&static_member_function)`, `.then(&Class::static_member_function)`, `.then(instance, &Class::member_function)` in Wangle.

C++ does not allow `.then(instance, &member_function)`, sadly.

This implementation just creates the closure for you and defers to the existing `then` implementations.

Test Plan: Added a test.

Reviewed By: hans@fb.com

FB internal diff: D1204954
parent d3ee99f7
......@@ -100,7 +100,7 @@ class Future {
Future<typename std::result_of<F(Try<T>&&)>::type> >::type
then(F&& func);
/// Variant where func returns a future<T> instead of a T. e.g.
/// Variant where func returns a Future<T> instead of a T. e.g.
///
/// Future<string> f2 = f1.then(
/// [](Try<T>&&) { return makeFuture<string>("foo"); });
......@@ -110,6 +110,70 @@ class Future {
Future<typename std::result_of<F(Try<T>&&)>::type::value_type> >::type
then(F&& func);
/// Variant where func is an ordinary function (static method, method)
///
/// R doWork(Try<T>&&);
///
/// Future<R> f2 = f1.then(doWork);
///
/// or
///
/// struct Worker {
/// static R doWork(Try<T>&&); }
///
/// Future<R> f2 = f1.then(&Worker::doWork);
template <class = T, class R = std::nullptr_t>
typename std::enable_if<!isFuture<R>::value, Future<R>>::type
inline then(R(*func)(Try<T>&&)) {
return then([func](Try<T>&& t) {
return (*func)(std::move(t));
});
}
/// Variant where func returns a Future<R> instead of a R. e.g.
///
/// struct Worker {
/// Future<R> doWork(Try<T>&&); }
///
/// Future<R> f2 = f1.then(&Worker::doWork);
template <class = T, class R = std::nullptr_t>
typename std::enable_if<isFuture<R>::value, R>::type
inline then(R(*func)(Try<T>&&)) {
return then([func](Try<T>&& t) {
return (*func)(std::move(t));
});
}
/// Variant where func is an member function
///
/// struct Worker {
/// R doWork(Try<T>&&); }
///
/// Worker *w;
/// Future<R> f2 = f1.then(w, &Worker::doWork);
template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
typename std::enable_if<!isFuture<R>::value, Future<R>>::type
inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
return then([instance, func](Try<T>&& t) {
return (instance->*func)(std::move(t));
});
}
/// Variant where func returns a Future<R> instead of a R. e.g.
///
/// struct Worker {
/// Future<R> doWork(Try<T>&&); }
///
/// Worker *w;
/// Future<R> f2 = f1.then(w, &Worker::doWork);
template <class = T, class R = std::nullptr_t, class Caller = std::nullptr_t>
typename std::enable_if<isFuture<R>::value, R>::type
inline then(Caller *instance, R(Caller::*func)(Try<T>&&)) {
return then([instance, func](Try<T>&& t) {
return (instance->*func)(std::move(t));
});
}
/// Convenience method for ignoring the value and creating a Future<void>.
/// Exceptions still propagate.
Future<void> then();
......
......@@ -91,6 +91,50 @@ TEST(Future, then) {
EXPECT_TRUE(f.isReady());
}
static string doWorkStatic(Try<string>&& t) {
return t.value() + ";static";
}
TEST(Future, thenFunction) {
struct Worker {
string doWork(Try<string>&& t) {
return t.value() + ";class";
}
static string doWorkStatic(Try<string>&& t) {
return t.value() + ";class-static";
}
} w;
auto f = makeFuture<string>("start")
.then(doWorkStatic)
.then(Worker::doWorkStatic)
.then(&w, &Worker::doWork);
EXPECT_EQ(f.value(), "start;static;class-static;class");
}
static Future<string> doWorkStaticFuture(Try<string>&& t) {
return makeFuture(t.value() + ";static");
}
TEST(Future, thenFunctionFuture) {
struct Worker {
Future<string> doWorkFuture(Try<string>&& t) {
return makeFuture(t.value() + ";class");
}
static Future<string> doWorkStaticFuture(Try<string>&& t) {
return makeFuture(t.value() + ";class-static");
}
} w;
auto f = makeFuture<string>("start")
.then(doWorkStaticFuture)
.then(Worker::doWorkStaticFuture)
.then(&w, &Worker::doWorkFuture);
EXPECT_EQ(f.value(), "start;static;class-static;class");
}
TEST(Future, value) {
auto f = makeFuture(unique_ptr<int>(new int(42)));
auto up = std::move(f.value());
......
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