Commit b50d0563 authored by James Sedgwick's avatar James Sedgwick Committed by Facebook Github Bot 9

Function::asStdFunction()

Summary:This is an ugly but occassionally useful hack to accomodate cases
where we want to propagate folly::Function but run into the brick wall that is
std::function

@override-unit-failures

Reviewed By: spacedentist

Differential Revision: D3118432

fb-gh-sync-id: 80ed56494dfcf60e0f266013d880107acabc7dcf
fbshipit-source-id: 80ed56494dfcf60e0f266013d880107acabc7dcf
parent 7f813725
......@@ -313,6 +313,20 @@ class FunctionTypeTraits<R(Args...) const>::ExecutorMixin {
InvokeFunctionPtr const invokePtr;
};
template <class Function>
struct InvokeFromSharedPtr final {
std::shared_ptr<Function> ptr_;
explicit InvokeFromSharedPtr(std::shared_ptr<Function> ptr)
: ptr_(std::move(ptr)) {}
template <typename... Args>
auto operator()(Args&&... args)
-> decltype((*ptr_)(std::forward<Args>(args)...)) {
return (*ptr_)(std::forward<Args>(args)...);
}
};
} // namespace function
} // namespace detail
} // namespace folly
......@@ -303,6 +303,16 @@ class Function final
*/
Function& operator=(Function&& rhs) noexcept(hasNoExceptMoveCtor());
/**
* Construct a std::function by moving in the contents of this `Function`.
* Note that the returned std::function will share its state (i.e. captured
* data) across all copies you make of it, so be very careful when copying.
*/
std::function<typename Traits::NonConstFunctionType> asStdFunction() && {
return detail::function::InvokeFromSharedPtr<Function>(
std::make_shared<Function>(std::move(*this)));
}
/**
* Constructs a `Function` by moving from one with different template
* parameters with regards to const-ness, no-except-movability and internal
......
......@@ -1230,3 +1230,75 @@ TEST(Function, ConvertReturnType) {
Function<CBase()> cf9 = std::move(f9);
EXPECT_EQ(cf9().x, 66);
}
TEST(Function, asStdFunction_void) {
int i = 0;
folly::Function<void()> f = [&] { ++i; };
auto sf = std::move(f).asStdFunction();
static_assert(std::is_same<decltype(sf), std::function<void()>>::value,
"std::function has wrong type");
sf();
EXPECT_EQ(1, i);
}
TEST(Function, asStdFunction_void_const) {
int i = 0;
folly::Function<void() const> f = [&] { ++i; };
auto sf = std::move(f).asStdFunction();
static_assert(std::is_same<decltype(sf), std::function<void()>>::value,
"std::function has wrong type");
sf();
EXPECT_EQ(1, i);
}
TEST(Function, asStdFunction_return) {
int i = 0;
folly::Function<int()> f = [&] {
++i;
return 42;
};
auto sf = std::move(f).asStdFunction();
static_assert(std::is_same<decltype(sf), std::function<int()>>::value,
"std::function has wrong type");
EXPECT_EQ(42, sf());
EXPECT_EQ(1, i);
}
TEST(Function, asStdFunction_return_const) {
int i = 0;
folly::Function<int() const> f = [&] {
++i;
return 42;
};
auto sf = std::move(f).asStdFunction();
static_assert(std::is_same<decltype(sf), std::function<int()>>::value,
"std::function has wrong type");
EXPECT_EQ(42, sf());
EXPECT_EQ(1, i);
}
TEST(Function, asStdFunction_args) {
int i = 0;
folly::Function<void(int, int)> f = [&](int x, int y) {
++i;
return x + y;
};
auto sf = std::move(f).asStdFunction();
static_assert(std::is_same<decltype(sf), std::function<void(int, int)>>::value,
"std::function has wrong type");
sf(42, 42);
EXPECT_EQ(1, i);
}
TEST(Function, asStdFunction_args_const) {
int i = 0;
folly::Function<void(int, int) const> f = [&](int x, int y) {
++i;
return x + y;
};
auto sf = std::move(f).asStdFunction();
static_assert(std::is_same<decltype(sf), std::function<void(int, int)>>::value,
"std::function has wrong type");
sf(42, 42);
EXPECT_EQ(1, i);
}
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