Commit 49f2f8b1 authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

allow passing function pointers to Future::onError()

Summary:
Add appropriate specializations for detail::Extract() so that you can pass a
plain function pointer to `onError()`.  Previously the code only worked with
member function pointers and functor-style objects.

Reviewed By: yfeldblum, wez

Differential Revision: D5286773

fbshipit-source-id: 67b44d1d7573eb1da501475045fd24ad4ab1c074
parent 61a0ef55
...@@ -119,6 +119,22 @@ struct Extract<R(Class::*)(Args...)> { ...@@ -119,6 +119,22 @@ struct Extract<R(Class::*)(Args...)> {
typedef typename ArgType<Args...>::FirstArg FirstArg; typedef typename ArgType<Args...>::FirstArg FirstArg;
}; };
template <typename R, typename... Args>
struct Extract<R (*)(Args...)> {
typedef isFuture<R> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
typedef typename ReturnsFuture::Inner RawReturn;
typedef typename ArgType<Args...>::FirstArg FirstArg;
};
template <typename R, typename... Args>
struct Extract<R (&)(Args...)> {
typedef isFuture<R> ReturnsFuture;
typedef Future<typename ReturnsFuture::Inner> Return;
typedef typename ReturnsFuture::Inner RawReturn;
typedef typename ArgType<Args...>::FirstArg FirstArg;
};
// gcc-4.8 refuses to capture a function reference in a lambda. This can be // gcc-4.8 refuses to capture a function reference in a lambda. This can be
// mitigated by casting them to function pointer types first. The following // mitigated by casting them to function pointer types first. The following
// helper is used in Future.h to achieve that where necessary. // helper is used in Future.h to achieve that where necessary.
......
...@@ -76,6 +76,15 @@ TEST(Future, makeFutureWithUnit) { ...@@ -76,6 +76,15 @@ TEST(Future, makeFutureWithUnit) {
EXPECT_EQ(1, count); EXPECT_EQ(1, count);
} }
namespace {
Future<int> onErrorHelperEggs(const eggs_t&) {
return makeFuture(10);
}
Future<int> onErrorHelperGeneric(const std::exception&) {
return makeFuture(20);
}
}
TEST(Future, onError) { TEST(Future, onError) {
bool theFlag = false; bool theFlag = false;
auto flag = [&]{ theFlag = true; }; auto flag = [&]{ theFlag = true; };
...@@ -191,6 +200,28 @@ TEST(Future, onError) { ...@@ -191,6 +200,28 @@ TEST(Future, onError) {
EXPECT_NO_THROW(f.value()); EXPECT_NO_THROW(f.value());
} }
// Function pointer
{
auto f = makeFuture()
.then([]() -> int { throw eggs; })
.onError(onErrorHelperEggs)
.onError(onErrorHelperGeneric);
EXPECT_EQ(10, f.value());
}
{
auto f = makeFuture()
.then([]() -> int { throw std::runtime_error("test"); })
.onError(onErrorHelperEggs)
.onError(onErrorHelperGeneric);
EXPECT_EQ(20, f.value());
}
{
auto f = makeFuture()
.then([]() -> int { throw std::runtime_error("test"); })
.onError(onErrorHelperEggs);
EXPECT_THROW(f.value(), std::runtime_error);
}
// No throw // No throw
{ {
auto f = makeFuture() auto f = makeFuture()
......
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