2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <folly/Function.h>
22 #include <folly/Memory.h>
23 #include <folly/portability/GTest.h>
25 using folly::Function;
28 int func_int_int_add_25(int x) {
31 int func_int_int_add_111(int x) {
34 float floatMult(float a, float b) {
38 template <class T, size_t S>
40 std::array<T, S> data = {{0}};
42 // Two operator() with different argument types.
43 // The InvokeReference tests use both
44 T const& operator()(size_t index) const {
47 T operator()(size_t index, T const& value) {
48 T oldvalue = data[index];
54 template <typename Ret, typename... Args>
55 void deduceArgs(Function<Ret(Args...)>) {}
59 // TEST =====================================================================
60 // InvokeFunctor & InvokeReference
62 TEST(Function, InvokeFunctor) {
63 Functor<int, 100> func;
65 sizeof(func) > sizeof(Function<int(size_t)>),
66 "sizeof(Function) is much larger than expected");
69 Function<int(size_t) const> getter = std::move(func);
71 // Function will allocate memory on the heap to store the functor object
72 EXPECT_TRUE(getter.hasAllocatedMemory());
74 EXPECT_EQ(123, getter(5));
77 TEST(Function, InvokeReference) {
78 Functor<int, 10> func;
81 // Have Functions for getter and setter, both referencing the same funtor
82 Function<int(size_t) const> getter = std::ref(func);
83 Function<int(size_t, int)> setter = std::ref(func);
85 EXPECT_EQ(123, getter(5));
86 EXPECT_EQ(123, setter(5, 456));
87 EXPECT_EQ(456, setter(5, 567));
88 EXPECT_EQ(567, getter(5));
91 // TEST =====================================================================
94 TEST(Function, Emptiness_T) {
96 EXPECT_EQ(f, nullptr);
97 EXPECT_EQ(nullptr, f);
99 EXPECT_THROW(f(98), std::bad_function_call);
101 Function<int(int)> g([](int x) { return x + 1; });
102 EXPECT_NE(g, nullptr);
103 EXPECT_NE(nullptr, g);
104 // Explicitly convert to bool to work around
105 // https://github.com/google/googletest/issues/429
106 EXPECT_TRUE(bool(g));
107 EXPECT_EQ(100, g(99));
109 Function<int(int)> h(&func_int_int_add_25);
110 EXPECT_NE(h, nullptr);
111 EXPECT_NE(nullptr, h);
112 EXPECT_TRUE(bool(h));
113 EXPECT_EQ(125, h(100));
116 EXPECT_EQ(h, nullptr);
117 EXPECT_EQ(nullptr, h);
119 EXPECT_THROW(h(101), std::bad_function_call);
122 // TEST =====================================================================
125 template <bool UseSwapMethod>
127 Function<int(int)> mf1(func_int_int_add_25);
128 Function<int(int)> mf2(func_int_int_add_111);
130 EXPECT_EQ(125, mf1(100));
131 EXPECT_EQ(211, mf2(100));
139 EXPECT_EQ(125, mf2(100));
140 EXPECT_EQ(211, mf1(100));
142 Function<int(int)> mf3(nullptr);
143 EXPECT_EQ(mf3, nullptr);
151 EXPECT_EQ(211, mf3(100));
152 EXPECT_EQ(nullptr, mf1);
154 Function<int(int)> mf4([](int x) { return x + 222; });
155 EXPECT_EQ(322, mf4(100));
162 EXPECT_EQ(211, mf4(100));
163 EXPECT_EQ(322, mf3(100));
170 EXPECT_EQ(nullptr, mf3);
171 EXPECT_EQ(322, mf1(100));
173 TEST(Function, SwapMethod) {
176 TEST(Function, SwapFunction) {
180 // TEST =====================================================================
183 TEST(Function, Bind) {
184 Function<float(float, float)> fnc = floatMult;
185 auto task = std::bind(std::move(fnc), 2.f, 4.f);
186 EXPECT_THROW(fnc(0, 0), std::bad_function_call);
187 EXPECT_EQ(8, task());
188 auto task2(std::move(task));
189 EXPECT_THROW(task(), std::bad_function_call);
190 EXPECT_EQ(8, task2());
193 // TEST =====================================================================
196 TEST(Function, NonCopyableLambda) {
197 auto unique_ptr_int = folly::make_unique<int>(900);
198 EXPECT_EQ(900, *unique_ptr_int);
203 (void)fooData; // suppress gcc warning about fooData not being used
205 auto functor = std::bind(
206 [fooData](std::unique_ptr<int>& up) mutable { return ++*up; },
207 std::move(unique_ptr_int));
209 EXPECT_EQ(901, functor());
211 Function<int(void)> func = std::move(functor);
212 EXPECT_TRUE(func.hasAllocatedMemory());
214 EXPECT_EQ(902, func());
217 // TEST =====================================================================
220 TEST(Function, OverloadedFunctor) {
221 struct OverloadedFunctor {
223 int operator()(int x) {
227 // variant 2 (const-overload of v1)
228 int operator()(int x) const {
233 int operator()(int x, int) {
237 // variant 4 (const-overload of v3)
238 int operator()(int x, int) const {
242 // variant 5 (non-const, has no const-overload)
243 int operator()(int x, char const*) {
247 // variant 6 (const only)
248 int operator()(int x, std::vector<int> const&) const {
252 OverloadedFunctor of;
254 Function<int(int)> variant1 = of;
255 EXPECT_EQ(100 + 1 * 15, variant1(15));
257 Function<int(int) const> variant2 = of;
258 EXPECT_EQ(100 + 2 * 16, variant2(16));
260 Function<int(int, int)> variant3 = of;
261 EXPECT_EQ(100 + 3 * 17, variant3(17, 0));
263 Function<int(int, int) const> variant4 = of;
264 EXPECT_EQ(100 + 4 * 18, variant4(18, 0));
266 Function<int(int, char const*)> variant5 = of;
267 EXPECT_EQ(100 + 5 * 19, variant5(19, "foo"));
269 Function<int(int, std::vector<int> const&)> variant6 = of;
270 EXPECT_EQ(100 + 6 * 20, variant6(20, {}));
271 EXPECT_EQ(100 + 6 * 20, variant6(20, {1, 2, 3}));
273 Function<int(int, std::vector<int> const&) const> variant6const = of;
274 EXPECT_EQ(100 + 6 * 21, variant6const(21, {}));
276 // Cast const-functions to non-const and the other way around: if the functor
277 // has both const and non-const operator()s for a given parameter signature,
278 // constructing a Function must select one of them, depending on
279 // whether the function type template parameter is const-qualified or not.
280 // When the const-ness is later changed (by moving the
281 // Function<R(Args...)const> into a Function<R(Args...)> or by
282 // calling the folly::constCastFunction which moves it into a
283 // Function<R(Args...)const>), the Function must still execute
284 // the initially selected function.
286 auto variant1_const = folly::constCastFunction(std::move(variant1));
287 EXPECT_THROW(variant1(0), std::bad_function_call);
288 EXPECT_EQ(100 + 1 * 22, variant1_const(22));
290 Function<int(int)> variant2_nonconst = std::move(variant2);
291 EXPECT_THROW(variant2(0), std::bad_function_call);
292 EXPECT_EQ(100 + 2 * 23, variant2_nonconst(23));
294 auto variant3_const = folly::constCastFunction(std::move(variant3));
295 EXPECT_THROW(variant3(0, 0), std::bad_function_call);
296 EXPECT_EQ(100 + 3 * 24, variant3_const(24, 0));
298 Function<int(int, int)> variant4_nonconst = std::move(variant4);
299 EXPECT_THROW(variant4(0, 0), std::bad_function_call);
300 EXPECT_EQ(100 + 4 * 25, variant4_nonconst(25, 0));
302 auto variant5_const = folly::constCastFunction(std::move(variant5));
303 EXPECT_THROW(variant5(0, ""), std::bad_function_call);
304 EXPECT_EQ(100 + 5 * 26, variant5_const(26, "foo"));
306 auto variant6_const = folly::constCastFunction(std::move(variant6));
307 EXPECT_THROW(variant6(0, {}), std::bad_function_call);
308 EXPECT_EQ(100 + 6 * 27, variant6_const(27, {}));
310 Function<int(int, std::vector<int> const&)> variant6const_nonconst =
311 std::move(variant6const);
312 EXPECT_THROW(variant6const(0, {}), std::bad_function_call);
313 EXPECT_EQ(100 + 6 * 28, variant6const_nonconst(28, {}));
316 // TEST =====================================================================
319 TEST(Function, Lambda) {
320 // Non-mutable lambdas: can be stored in a non-const...
321 Function<int(int)> func = [](int x) { return 1000 + x; };
322 EXPECT_EQ(1001, func(1));
324 // ...as well as in a const Function
325 Function<int(int) const> func_const = [](int x) { return 2000 + x; };
326 EXPECT_EQ(2001, func_const(1));
328 // Mutable lambda: can only be stored in a const Function:
330 Function<int()> func_mutable = [number]() mutable { return ++number; };
331 EXPECT_EQ(3001, func_mutable());
332 EXPECT_EQ(3002, func_mutable());
334 // test after const-casting
336 Function<int(int) const> func_made_const =
337 folly::constCastFunction(std::move(func));
338 EXPECT_EQ(1002, func_made_const(2));
339 EXPECT_THROW(func(0), std::bad_function_call);
341 Function<int(int)> func_const_made_nonconst = std::move(func_const);
342 EXPECT_EQ(2002, func_const_made_nonconst(2));
343 EXPECT_THROW(func_const(0), std::bad_function_call);
345 Function<int() const> func_mutable_made_const =
346 folly::constCastFunction(std::move(func_mutable));
347 EXPECT_EQ(3003, func_mutable_made_const());
348 EXPECT_EQ(3004, func_mutable_made_const());
349 EXPECT_THROW(func_mutable(), std::bad_function_call);
352 // TEST =====================================================================
353 // DataMember & MemberFunction
365 TEST(Function, DataMember) {
367 MemberFunc const& cmf = mf;
370 Function<int(MemberFunc const*)> data_getter1 = &MemberFunc::x;
371 EXPECT_EQ(123, data_getter1(&cmf));
372 Function<int(MemberFunc*)> data_getter2 = &MemberFunc::x;
373 EXPECT_EQ(123, data_getter2(&mf));
374 Function<int(MemberFunc const&)> data_getter3 = &MemberFunc::x;
375 EXPECT_EQ(123, data_getter3(cmf));
376 Function<int(MemberFunc&)> data_getter4 = &MemberFunc::x;
377 EXPECT_EQ(123, data_getter4(mf));
380 TEST(Function, MemberFunction) {
382 MemberFunc const& cmf = mf;
385 Function<int(MemberFunc const*)> getter1 = &MemberFunc::getX;
386 EXPECT_EQ(123, getter1(&cmf));
387 Function<int(MemberFunc*)> getter2 = &MemberFunc::getX;
388 EXPECT_EQ(123, getter2(&mf));
389 Function<int(MemberFunc const&)> getter3 = &MemberFunc::getX;
390 EXPECT_EQ(123, getter3(cmf));
391 Function<int(MemberFunc&)> getter4 = &MemberFunc::getX;
392 EXPECT_EQ(123, getter4(mf));
394 Function<void(MemberFunc*, int)> setter1 = &MemberFunc::setX;
396 EXPECT_EQ(234, mf.x);
398 Function<void(MemberFunc&, int)> setter2 = &MemberFunc::setX;
400 EXPECT_EQ(345, mf.x);
403 // TEST =====================================================================
404 // CaptureCopyMoveCount & ParameterCopyMoveCount
406 class CopyMoveTracker {
408 struct ConstructorTag {};
410 CopyMoveTracker() = delete;
411 explicit CopyMoveTracker(ConstructorTag)
412 : data_(std::make_shared<std::pair<size_t, size_t>>(0, 0)) {}
414 CopyMoveTracker(CopyMoveTracker const& o) noexcept : data_(o.data_) {
417 CopyMoveTracker& operator=(CopyMoveTracker const& o) noexcept {
423 CopyMoveTracker(CopyMoveTracker&& o) noexcept : data_(o.data_) {
426 CopyMoveTracker& operator=(CopyMoveTracker&& o) noexcept {
432 size_t copyCount() const {
435 size_t moveCount() const {
436 return data_->second;
438 size_t refCount() const {
439 return data_.use_count();
441 void resetCounters() {
442 data_->first = data_->second = 0;
447 std::shared_ptr<std::pair<size_t, size_t>> data_;
450 TEST(Function, CaptureCopyMoveCount) {
451 // This test checks that no unnecessary copies/moves are made.
453 CopyMoveTracker cmt(CopyMoveTracker::ConstructorTag{});
454 EXPECT_EQ(0, cmt.copyCount());
455 EXPECT_EQ(0, cmt.moveCount());
456 EXPECT_EQ(1, cmt.refCount());
458 // Move into lambda, move lambda into Function
459 auto lambda1 = [cmt = std::move(cmt)]() {
460 return cmt.moveCount();
462 Function<size_t(void)> uf1 = std::move(lambda1);
464 // Max copies: 0. Max copy+moves: 2.
465 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
466 EXPECT_LE(cmt.copyCount(), 0);
470 // Move into lambda, copy lambda into Function
471 auto lambda2 = [cmt = std::move(cmt)]() {
472 return cmt.moveCount();
474 Function<size_t(void)> uf2 = lambda2;
476 // Max copies: 1. Max copy+moves: 2.
477 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
478 EXPECT_LE(cmt.copyCount(), 1);
480 // Invoking Function must not make copies/moves of the callable
484 EXPECT_EQ(0, cmt.copyCount());
485 EXPECT_EQ(0, cmt.moveCount());
488 TEST(Function, ParameterCopyMoveCount) {
489 // This test checks that no unnecessary copies/moves are made.
491 CopyMoveTracker cmt(CopyMoveTracker::ConstructorTag{});
492 EXPECT_EQ(0, cmt.copyCount());
493 EXPECT_EQ(0, cmt.moveCount());
494 EXPECT_EQ(1, cmt.refCount());
497 Function<size_t(CopyMoveTracker)> uf1 = [](CopyMoveTracker c) {
498 return c.moveCount();
503 // Max copies: 1. Max copy+moves: 2.
504 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
505 EXPECT_LE(cmt.copyCount(), 1);
509 // Max copies: 1. Max copy+moves: 2.
510 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
511 EXPECT_LE(cmt.copyCount(), 0);
514 Function<size_t(CopyMoveTracker&)> uf2 = [](CopyMoveTracker& c) {
515 return c.moveCount();
520 // Max copies: 0. Max copy+moves: 0.
521 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
522 EXPECT_LE(cmt.copyCount(), 0);
524 // pass by const reference
525 Function<size_t(CopyMoveTracker const&)> uf3 = [](CopyMoveTracker const& c) {
526 return c.moveCount();
531 // Max copies: 0. Max copy+moves: 0.
532 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
533 EXPECT_LE(cmt.copyCount(), 0);
535 // pass by rvalue reference
536 Function<size_t(CopyMoveTracker &&)> uf4 = [](CopyMoveTracker&& c) {
537 return c.moveCount();
542 // Max copies: 0. Max copy+moves: 0.
543 EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
544 EXPECT_LE(cmt.copyCount(), 0);
547 // TEST =====================================================================
548 // VariadicTemplate & VariadicArguments
550 struct VariadicTemplateSum {
551 int operator()() const {
554 template <class... Args>
555 int operator()(int x, Args... args) const {
556 return x + (*this)(args...);
560 TEST(Function, VariadicTemplate) {
561 Function<int(int)> uf1 = VariadicTemplateSum();
562 Function<int(int, int)> uf2 = VariadicTemplateSum();
563 Function<int(int, int, int)> uf3 = VariadicTemplateSum();
565 EXPECT_EQ(66, uf1(66));
566 EXPECT_EQ(99, uf2(55, 44));
567 EXPECT_EQ(66, uf3(33, 22, 11));
570 struct VariadicArgumentsSum {
571 int operator()(int count, ...) const {
574 va_start(args, count);
575 for (int i = 0; i < count; ++i) {
576 result += va_arg(args, int);
583 TEST(Function, VariadicArguments) {
584 Function<int(int)> uf1 = VariadicArgumentsSum();
585 Function<int(int, int)> uf2 = VariadicArgumentsSum();
586 Function<int(int, int, int)> uf3 = VariadicArgumentsSum();
588 EXPECT_EQ(0, uf1(0));
589 EXPECT_EQ(66, uf2(1, 66));
590 EXPECT_EQ(99, uf3(2, 55, 44));
593 // TEST =====================================================================
594 // SafeCaptureByReference
596 // A function can use Function const& as a parameter to signal that it
597 // is safe to pass a lambda that captures local variables by reference.
598 // It is safe because we know the function called can only invoke the
599 // Function until it returns. It can't store a copy of the Function
600 // (because it's not copyable), and it can't move the Function somewhere
601 // else (because it gets only a const&).
603 template <typename T>
606 Function<void(typename T::value_type const&) const> const& func) {
607 for (auto const& elem : range) {
612 TEST(Function, SafeCaptureByReference) {
613 std::vector<int> const vec = {20, 30, 40, 2, 3, 4, 200, 300, 400};
617 // for_each's second parameter is of type Function<...> const&.
618 // Hence we know we can safely pass it a lambda that references local
619 // variables. There is no way the reference to x will be stored anywhere.
620 for_each<std::vector<int>>(vec, [&sum](int x) { sum += x; });
622 // gcc versions before 4.9 cannot deduce the type T in the above call
623 // to for_each. Modern compiler versions can compile the following line:
624 // for_each(vec, [&sum](int x) { sum += x; });
629 // TEST =====================================================================
632 TEST(Function, IgnoreReturnValue) {
635 // Assign a lambda that return int to a folly::Function that returns void.
636 Function<void()> f = [&]() -> int { return ++x; };
642 Function<int()> g = [&]() -> int { return ++x; };
643 Function<void()> cg = std::move(g);
650 // TEST =====================================================================
651 // ReturnConvertible, ConvertReturnType
653 TEST(Function, ReturnConvertible) {
657 struct CDerived : CBase {};
659 Function<double()> f1 = []() -> int { return 5; };
660 EXPECT_EQ(5.0, f1());
662 Function<int()> f2 = []() -> double { return 5.2; };
668 Function<CBase const&()> f3 = [&]() -> CDerived const& { return derived; };
669 EXPECT_EQ(55, f3().x);
671 Function<CBase const&()> f4 = [&]() -> CDerived& { return derived; };
672 EXPECT_EQ(55, f4().x);
674 Function<CBase&()> f5 = [&]() -> CDerived& { return derived; };
675 EXPECT_EQ(55, f5().x);
677 Function<CBase const*()> f6 = [&]() -> CDerived const* { return &derived; };
678 EXPECT_EQ(f6()->x, 55);
680 Function<CBase const*()> f7 = [&]() -> CDerived* { return &derived; };
681 EXPECT_EQ(55, f7()->x);
683 Function<CBase*()> f8 = [&]() -> CDerived* { return &derived; };
684 EXPECT_EQ(55, f8()->x);
686 Function<CBase()> f9 = [&]() -> CDerived {
691 EXPECT_EQ(66, f9().x);
694 TEST(Function, ConvertReturnType) {
698 struct CDerived : CBase {};
700 Function<int()> f1 = []() -> int { return 5; };
701 Function<double()> cf1 = std::move(f1);
702 EXPECT_EQ(5.0, cf1());
703 Function<int()> ccf1 = std::move(cf1);
704 EXPECT_EQ(5, ccf1());
706 Function<double()> f2 = []() -> double { return 5.2; };
707 Function<int()> cf2 = std::move(f2);
709 Function<double()> ccf2 = std::move(cf2);
710 EXPECT_EQ(5.0, ccf2());
715 Function<CDerived const&()> f3 = [&]() -> CDerived const& { return derived; };
716 Function<CBase const&()> cf3 = std::move(f3);
717 EXPECT_EQ(55, cf3().x);
719 Function<CDerived&()> f4 = [&]() -> CDerived& { return derived; };
720 Function<CBase const&()> cf4 = std::move(f4);
721 EXPECT_EQ(55, cf4().x);
723 Function<CDerived&()> f5 = [&]() -> CDerived& { return derived; };
724 Function<CBase&()> cf5 = std::move(f5);
725 EXPECT_EQ(55, cf5().x);
727 Function<CDerived const*()> f6 = [&]() -> CDerived const* {
730 Function<CBase const*()> cf6 = std::move(f6);
731 EXPECT_EQ(55, cf6()->x);
733 Function<CDerived const*()> f7 = [&]() -> CDerived* { return &derived; };
734 Function<CBase const*()> cf7 = std::move(f7);
735 EXPECT_EQ(55, cf7()->x);
737 Function<CDerived*()> f8 = [&]() -> CDerived* { return &derived; };
738 Function<CBase*()> cf8 = std::move(f8);
739 EXPECT_EQ(55, cf8()->x);
741 Function<CDerived()> f9 = [&]() -> CDerived {
746 Function<CBase()> cf9 = std::move(f9);
747 EXPECT_EQ(66, cf9().x);
750 // TEST =====================================================================
753 TEST(Function, asStdFunction_void) {
755 folly::Function<void()> f = [&] { ++i; };
756 auto sf = std::move(f).asStdFunction();
757 static_assert(std::is_same<decltype(sf), std::function<void()>>::value,
758 "std::function has wrong type");
763 TEST(Function, asStdFunction_void_const) {
765 folly::Function<void() const> f = [&] { ++i; };
766 auto sf = std::move(f).asStdFunction();
767 static_assert(std::is_same<decltype(sf), std::function<void()>>::value,
768 "std::function has wrong type");
773 TEST(Function, asStdFunction_return) {
775 folly::Function<int()> f = [&] {
779 auto sf = std::move(f).asStdFunction();
780 static_assert(std::is_same<decltype(sf), std::function<int()>>::value,
781 "std::function has wrong type");
786 TEST(Function, asStdFunction_return_const) {
788 folly::Function<int() const> f = [&] {
792 auto sf = std::move(f).asStdFunction();
793 static_assert(std::is_same<decltype(sf), std::function<int()>>::value,
794 "std::function has wrong type");
799 TEST(Function, asStdFunction_args) {
801 folly::Function<void(int, int)> f = [&](int x, int y) {
805 auto sf = std::move(f).asStdFunction();
806 static_assert(std::is_same<decltype(sf), std::function<void(int, int)>>::value,
807 "std::function has wrong type");
812 TEST(Function, asStdFunction_args_const) {
814 folly::Function<void(int, int) const> f = [&](int x, int y) {
818 auto sf = std::move(f).asStdFunction();
819 static_assert(std::is_same<decltype(sf), std::function<void(int, int)>>::value,
820 "std::function has wrong type");
825 // TEST =====================================================================
828 TEST(Function, asSharedProxy_void) {
830 folly::Function<void()> f = [&i] { ++i; };
831 auto sp = std::move(f).asSharedProxy();
839 TEST(Function, asSharedProxy_void_const) {
841 folly::Function<void() const> f = [&i] { ++i; };
842 auto sp = std::move(f).asSharedProxy();
850 TEST(Function, asSharedProxy_return) {
851 folly::Function<int()> f = [i = 0]() mutable {
855 auto sp = std::move(f).asSharedProxy();
858 EXPECT_EQ(2, spcopy());
861 TEST(Function, asSharedProxy_return_const) {
863 folly::Function<int() const> f = [&i] {
867 auto sp = std::move(f).asSharedProxy();
870 EXPECT_EQ(2, spcopy());
873 TEST(Function, asSharedProxy_args) {
875 folly::Function<int(int, int)> f = [&](int x, int y) mutable {
879 auto sp = std::move(f).asSharedProxy();
881 EXPECT_EQ(120, sp(100, 10));
883 EXPECT_EQ(120, spcopy(100, 10));
887 TEST(Function, asSharedProxy_args_const) {
889 folly::Function<int(int, int) const> f = [&i](int x, int y) {
891 return x * 100 + y * 10 + i;
893 auto sp = std::move(f).asSharedProxy();
895 EXPECT_EQ(561, sp(5, 6));
896 EXPECT_EQ(562, spcopy(5, 6));
899 TEST(Function, NoAllocatedMemoryAfterMove) {
900 Functor<int, 100> foo;
902 Function<int(size_t)> func = foo;
903 EXPECT_TRUE(func.hasAllocatedMemory());
905 Function<int(size_t)> func2 = std::move(func);
906 EXPECT_TRUE(func2.hasAllocatedMemory());
907 EXPECT_FALSE(func.hasAllocatedMemory());
910 TEST(Function, ConstCastEmbedded) {
912 auto functor = [&x]() { ++x; };
914 Function<void() const> func(functor);
915 EXPECT_FALSE(func.hasAllocatedMemory());
917 Function<void()> func2(std::move(func));
918 EXPECT_FALSE(func2.hasAllocatedMemory());
921 TEST(Function, EmptyAfterConstCast) {
922 Function<int(size_t)> func;
925 Function<int(size_t) const> func2 = constCastFunction(std::move(func));
929 TEST(Function, SelfMoveAssign) {
930 Function<int()> f = [] { return 0; };
931 Function<int()>& g = f;
933 EXPECT_TRUE(bool(f));
936 TEST(Function, DeducableArguments) {
937 deduceArgs(Function<void()>{[] {}});
938 deduceArgs(Function<void(int, float)>{[](int, float) {}});
939 deduceArgs(Function<int(int, float)>{[](int i, float) { return i; }});