return fn.call_(fn.data_, static_cast<Args&&>(args)...);
}
- struct SharedFunctionImpl {
+ class SharedProxy {
std::shared_ptr<Function<ReturnType(Args...)>> sp_;
+
+ public:
+ explicit SharedProxy(Function<ReturnType(Args...)>&& func)
+ : sp_(std::make_shared<Function<ReturnType(Args...)>>(
+ std::move(func))) {}
ReturnType operator()(Args&&... args) const {
return (*sp_)(static_cast<Args&&>(args)...);
}
return fn.call_(fn.data_, static_cast<Args&&>(args)...);
}
- struct SharedFunctionImpl {
+ struct SharedProxy {
std::shared_ptr<Function<ReturnType(Args...) const>> sp_;
+
+ public:
+ explicit SharedProxy(Function<ReturnType(Args...) const>&& func)
+ : sp_(std::make_shared<Function<ReturnType(Args...) const>>(
+ std::move(func))) {}
ReturnType operator()(Args&&... args) const {
return (*sp_)(static_cast<Args&&>(args)...);
}
return exec_(Op::HEAP, nullptr, nullptr);
}
+ using typename Traits::SharedProxy;
+
+ /**
+ * Move this `Function` into a copyable callable object, of which all copies
+ * share the state.
+ */
+ SharedProxy asSharedProxy() && {
+ return SharedProxy{std::move(*this)};
+ }
+
/**
* 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::NonConstSignature> asStdFunction() && {
- using Impl = typename Traits::SharedFunctionImpl;
- return Impl{std::make_shared<Function>(std::move(*this))};
+ return std::move(*this).asSharedProxy();
}
};
FOLLY_POP_WARNING
EXPECT_EQ(1, i);
}
+// TEST =====================================================================
+// asSharedProxy_*
+
+TEST(Function, asSharedProxy_void) {
+ int i = 0;
+ folly::Function<void()> f = [&i] { ++i; };
+ auto sp = std::move(f).asSharedProxy();
+ auto spcopy = sp;
+ sp();
+ EXPECT_EQ(1, i);
+ spcopy();
+ EXPECT_EQ(2, i);
+}
+
+TEST(Function, asSharedProxy_void_const) {
+ int i = 0;
+ folly::Function<void() const> f = [&i] { ++i; };
+ auto sp = std::move(f).asSharedProxy();
+ auto spcopy = sp;
+ sp();
+ EXPECT_EQ(1, i);
+ spcopy();
+ EXPECT_EQ(2, i);
+}
+
+TEST(Function, asSharedProxy_return) {
+ folly::Function<int()> f = [i = 0]() mutable {
+ ++i;
+ return i;
+ };
+ auto sp = std::move(f).asSharedProxy();
+ auto spcopy = sp;
+ EXPECT_EQ(1, sp());
+ EXPECT_EQ(2, spcopy());
+}
+
+TEST(Function, asSharedProxy_return_const) {
+ int i = 0;
+ folly::Function<int() const> f = [&i] {
+ ++i;
+ return i;
+ };
+ auto sp = std::move(f).asSharedProxy();
+ auto spcopy = sp;
+ EXPECT_EQ(1, sp());
+ EXPECT_EQ(2, spcopy());
+}
+
+TEST(Function, asSharedProxy_args) {
+ int i = 0;
+ folly::Function<int(int, int)> f = [&](int x, int y) mutable {
+ ++i;
+ return x + y * 2;
+ };
+ auto sp = std::move(f).asSharedProxy();
+ auto spcopy = sp;
+ EXPECT_EQ(120, sp(100, 10));
+ EXPECT_EQ(1, i);
+ EXPECT_EQ(120, spcopy(100, 10));
+ EXPECT_EQ(2, i);
+}
+
+TEST(Function, asSharedProxy_args_const) {
+ int i = 0;
+ folly::Function<int(int, int) const> f = [&i](int x, int y) {
+ ++i;
+ return x * 100 + y * 10 + i;
+ };
+ auto sp = std::move(f).asSharedProxy();
+ auto spcopy = sp;
+ EXPECT_EQ(561, sp(5, 6));
+ EXPECT_EQ(562, spcopy(5, 6));
+}
+
TEST(Function, NoAllocatedMemoryAfterMove) {
Functor<int, 100> foo;