Function::asStdFunction()
[folly.git] / folly / test / FunctionTest.cpp
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <cstdarg>
18
19 #include <folly/Function.h>
20
21 #include <folly/Memory.h>
22 #include <gtest/gtest.h>
23
24 using folly::FunctionMoveCtor;
25 using folly::Function;
26
27 namespace {
28 int func_int_int_add_25(int x) {
29   return x + 25;
30 }
31 int func_int_int_add_111(int x) {
32   return x + 111;
33 }
34 int func_int_return_987() {
35   return 987;
36 }
37 float floatMult(float a, float b) {
38   return a * b;
39 }
40
41 template <class T, size_t S>
42 struct Functor {
43   std::array<T, S> data = {{0}};
44
45   // Two operator() with different argument types.
46   // The InvokeReference tests use both
47   T const& operator()(size_t index) const {
48     return data[index];
49   }
50   T operator()(size_t index, T const& value) {
51     T oldvalue = data[index];
52     data[index] = value;
53     return oldvalue;
54   }
55 };
56
57 // TEST =====================================================================
58 // NoExceptMovable
59
60 struct MoveMayThrow {
61   bool doThrow{false};
62
63   MoveMayThrow() = default;
64   MoveMayThrow(MoveMayThrow const&) = default;
65   MoveMayThrow& operator=(MoveMayThrow const&) = default;
66   MoveMayThrow(MoveMayThrow&&) noexcept(false) {
67     if (doThrow) {
68       throw std::runtime_error("MoveMayThrow(MoveMayThrow&&)");
69     }
70   }
71   MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) {
72     if (doThrow) {
73       throw std::runtime_error("MoveMayThrow::operator=(MoveMayThrow&&)");
74     }
75     return *this;
76   }
77 };
78 }
79
80 TEST(Function, NoExceptMovable) {
81   // callable_noexcept is noexcept-movable
82   auto callable_noexcept = [](int x) { return x + 1; };
83   EXPECT_TRUE(
84       std::is_nothrow_move_constructible<decltype(callable_noexcept)>::value);
85
86   // callable_throw may throw when moved
87   MoveMayThrow mmt;
88   auto callable_throw = [mmt](int x) { return x + 10; };
89   EXPECT_FALSE(
90       std::is_nothrow_move_constructible<decltype(callable_throw)>::value);
91
92   // callable_noexcept can be stored in the Function object
93   Function<int(int), FunctionMoveCtor::NO_THROW> func(callable_noexcept);
94   EXPECT_EQ(func(42), 43);
95   EXPECT_FALSE(func.hasAllocatedMemory());
96   EXPECT_TRUE(std::is_nothrow_move_constructible<decltype(func)>::value);
97
98   // callable_throw cannot be stored in the Function object,
99   // because Function guarantees noexcept-movability, but
100   // callable_throw may throw when moved
101   Function<int(int), FunctionMoveCtor::NO_THROW> func_safe_move(callable_throw);
102   EXPECT_EQ(func_safe_move(42), 52);
103   EXPECT_TRUE(func_safe_move.hasAllocatedMemory());
104   EXPECT_TRUE(
105       std::is_nothrow_move_constructible<decltype(func_safe_move)>::value);
106
107   // callable_throw can be stored in the Function object when
108   // the NoExceptMovable template parameter is set to NO
109   Function<int(int), FunctionMoveCtor::MAY_THROW> func_movethrows(
110       callable_throw);
111   EXPECT_EQ(func_movethrows(42), 52);
112   EXPECT_FALSE(func_movethrows.hasAllocatedMemory());
113   EXPECT_FALSE(
114       std::is_nothrow_move_constructible<decltype(func_movethrows)>::value);
115 }
116
117 // TEST =====================================================================
118 // InvokeFunctor & InvokeReference
119
120 template <FunctionMoveCtor NEM, size_t S>
121 void invoke_functor_test() {
122   Functor<int, 100> func;
123   func(5, 123);
124
125   // Try Functions with differently sized storage areas
126   // S=0: request storage for functors of size 0. The storage size
127   // will be actually larger, because there is a lower limit which
128   // still allows to store at least pointers to functors on the heap.
129   // S=1: request minimum storage size of 0.5x the sizeof(func)
130   // S=2: request sizeof(func)
131   // S=3: request 1.5*sizeof(func)
132   Function<int(size_t) const, NEM, sizeof(func)* S / 2> getter =
133       std::move(func);
134
135   // Function will allocate memory on the heap to store
136   // the functor object if the internal storage area is smaller than
137   // sizeof(func).
138   EXPECT_EQ(getter.hasAllocatedMemory(), S < 2);
139
140   EXPECT_EQ(getter(5), 123);
141 }
142 TEST(Function, InvokeFunctor_T0) {
143   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 0>();
144 }
145 TEST(Function, InvokeFunctor_N0) {
146   invoke_functor_test<FunctionMoveCtor::NO_THROW, 0>();
147 }
148 TEST(Function, InvokeFunctor_T1) {
149   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 1>();
150 }
151 TEST(Function, InvokeFunctor_N1) {
152   invoke_functor_test<FunctionMoveCtor::NO_THROW, 1>();
153 }
154 TEST(Function, InvokeFunctor_T2) {
155   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 2>();
156 }
157 TEST(Function, InvokeFunctor_N2) {
158   invoke_functor_test<FunctionMoveCtor::NO_THROW, 2>();
159 }
160 TEST(Function, InvokeFunctor_T3) {
161   invoke_functor_test<FunctionMoveCtor::MAY_THROW, 3>();
162 }
163 TEST(Function, InvokeFunctor_N3) {
164   invoke_functor_test<FunctionMoveCtor::NO_THROW, 3>();
165 }
166
167 template <FunctionMoveCtor NEM>
168 void invoke_reference_test() {
169   Functor<int, 10> func;
170   func(5, 123);
171
172   // Have Functions for getter and setter, both referencing the
173   // same funtor
174   Function<int(size_t) const, NEM, 0> getter = std::ref(func);
175   Function<int(size_t, int), NEM, 0> setter = std::ref(func);
176
177   EXPECT_EQ(getter(5), 123);
178   EXPECT_EQ(setter(5, 456), 123);
179   EXPECT_EQ(setter(5, 567), 456);
180   EXPECT_EQ(getter(5), 567);
181 }
182 TEST(Function, InvokeReference_T) {
183   invoke_reference_test<FunctionMoveCtor::MAY_THROW>();
184 }
185 TEST(Function, InvokeReference_N) {
186   invoke_reference_test<FunctionMoveCtor::NO_THROW>();
187 }
188
189 // TEST =====================================================================
190 // Emptiness
191
192 template <FunctionMoveCtor NEM>
193 void emptiness_test() {
194   Function<int(int), NEM> f;
195   EXPECT_EQ(f, nullptr);
196   EXPECT_EQ(nullptr, f);
197   EXPECT_FALSE(f);
198   EXPECT_THROW(f(98), std::bad_function_call);
199
200   Function<int(int), NEM> g([](int x) { return x + 1; });
201   EXPECT_NE(g, nullptr);
202   EXPECT_NE(nullptr, g);
203   EXPECT_TRUE(g);
204   EXPECT_EQ(g(99), 100);
205
206   Function<int(int), NEM> h(&func_int_int_add_25);
207   EXPECT_NE(h, nullptr);
208   EXPECT_NE(nullptr, h);
209   EXPECT_TRUE(h);
210   EXPECT_EQ(h(100), 125);
211
212   h = {};
213   EXPECT_EQ(h, nullptr);
214   EXPECT_EQ(nullptr, h);
215   EXPECT_FALSE(h);
216   EXPECT_THROW(h(101), std::bad_function_call);
217 }
218
219 TEST(Function, Emptiness_T) {
220   emptiness_test<FunctionMoveCtor::MAY_THROW>();
221 }
222 TEST(Function, Emptiness_N) {
223   emptiness_test<FunctionMoveCtor::NO_THROW>();
224 }
225
226 // TEST =====================================================================
227 // Types
228
229 TEST(Function, Types) {
230   EXPECT_TRUE((
231       !std::is_base_of<std::unary_function<int, int>, Function<int()>>::value));
232   EXPECT_TRUE(
233       (!std::is_base_of<std::binary_function<int, int, int>, Function<int()>>::
234            value));
235   EXPECT_TRUE((std::is_same<Function<int()>::ResultType, int>::value));
236
237   EXPECT_TRUE((
238       std::is_base_of<std::unary_function<int, double>, Function<double(int)>>::
239           value));
240   EXPECT_TRUE((!std::is_base_of<
241                std::binary_function<int, int, double>,
242                Function<double(int)>>::value));
243   EXPECT_TRUE((std::is_same<Function<double(int)>::ResultType, double>::value));
244   EXPECT_TRUE(
245       (std::is_same<Function<double(int)>::result_type, double>::value));
246   EXPECT_TRUE((std::is_same<Function<double(int)>::argument_type, int>::value));
247
248   EXPECT_TRUE((!std::is_base_of<
249                std::unary_function<int, double>,
250                Function<double(int, char)>>::value));
251   EXPECT_TRUE((std::is_base_of<
252                std::binary_function<int, char, double>,
253                Function<double(int, char)>>::value));
254   EXPECT_TRUE(
255       (std::is_same<Function<double(int, char)>::ResultType, double>::value));
256   EXPECT_TRUE(
257       (std::is_same<Function<double(int, char)>::result_type, double>::value));
258   EXPECT_TRUE(
259       (std::is_same<Function<double(int, char)>::first_argument_type, int>::
260            value));
261   EXPECT_TRUE(
262       (std::is_same<Function<double(int, char)>::second_argument_type, char>::
263            value));
264 }
265
266 // TEST =====================================================================
267 // Swap
268
269 template <FunctionMoveCtor NEM1, FunctionMoveCtor NEM2, bool UseSwapMethod>
270 void swap_test() {
271   Function<int(int), NEM1> mf1(func_int_int_add_25);
272   Function<int(int), NEM2> mf2(func_int_int_add_111);
273
274   EXPECT_EQ(mf1(100), 125);
275   EXPECT_EQ(mf2(100), 211);
276
277   if (UseSwapMethod) {
278     mf1.swap(mf2);
279   } else {
280     swap(mf1, mf2);
281   }
282
283   EXPECT_EQ(mf2(100), 125);
284   EXPECT_EQ(mf1(100), 211);
285
286   Function<int(int)> mf3(nullptr);
287   EXPECT_EQ(mf3, nullptr);
288
289   if (UseSwapMethod) {
290     mf1.swap(mf3);
291   } else {
292     swap(mf1, mf3);
293   }
294
295   EXPECT_EQ(mf3(100), 211);
296   EXPECT_EQ(mf1, nullptr);
297
298   Function<int(int)> mf4([](int x) { return x + 222; });
299   EXPECT_EQ(mf4(100), 322);
300
301   if (UseSwapMethod) {
302     mf4.swap(mf3);
303   } else {
304     swap(mf4, mf3);
305   }
306   EXPECT_EQ(mf4(100), 211);
307   EXPECT_EQ(mf3(100), 322);
308
309   if (UseSwapMethod) {
310     mf3.swap(mf1);
311   } else {
312     swap(mf3, mf1);
313   }
314   EXPECT_EQ(mf3, nullptr);
315   EXPECT_EQ(mf1(100), 322);
316 }
317 TEST(Function, SwapMethod_TT) {
318   swap_test<FunctionMoveCtor::MAY_THROW, FunctionMoveCtor::MAY_THROW, true>();
319 }
320 TEST(Function, SwapMethod_TN) {
321   swap_test<FunctionMoveCtor::MAY_THROW, FunctionMoveCtor::NO_THROW, true>();
322 }
323 TEST(Function, SwapMethod_NT) {
324   swap_test<FunctionMoveCtor::NO_THROW, FunctionMoveCtor::MAY_THROW, true>();
325 }
326 TEST(Function, SwapMethod_NN) {
327   swap_test<FunctionMoveCtor::NO_THROW, FunctionMoveCtor::NO_THROW, true>();
328 }
329 TEST(Function, SwapFunction_TT) {
330   swap_test<FunctionMoveCtor::MAY_THROW, FunctionMoveCtor::MAY_THROW, false>();
331 }
332 TEST(Function, SwapFunction_TN) {
333   swap_test<FunctionMoveCtor::MAY_THROW, FunctionMoveCtor::NO_THROW, false>();
334 }
335 TEST(Function, SwapFunction_NT) {
336   swap_test<FunctionMoveCtor::NO_THROW, FunctionMoveCtor::MAY_THROW, false>();
337 }
338 TEST(Function, SwapFunction_NN) {
339   swap_test<FunctionMoveCtor::NO_THROW, FunctionMoveCtor::NO_THROW, false>();
340 }
341
342 // TEST =====================================================================
343 // Bind
344
345 template <FunctionMoveCtor NEM>
346 void bind_test() {
347   Function<float(float, float), NEM> fnc = floatMult;
348   auto task = std::bind(std::move(fnc), 2.f, 4.f);
349   EXPECT_THROW(fnc(0, 0), std::bad_function_call);
350   EXPECT_EQ(task(), 8);
351   auto task2(std::move(task));
352   EXPECT_THROW(task(), std::bad_function_call);
353   EXPECT_EQ(task2(), 8);
354 }
355 TEST(Function, Bind_T) {
356   bind_test<FunctionMoveCtor::MAY_THROW>();
357 }
358 TEST(Function, Bind_N) {
359   bind_test<FunctionMoveCtor::NO_THROW>();
360 }
361
362 // TEST =====================================================================
363 // NonCopyableLambda
364
365 template <FunctionMoveCtor NEM, size_t S>
366 void non_copyable_lambda_test() {
367   auto unique_ptr_int = folly::make_unique<int>(900);
368   EXPECT_EQ(*unique_ptr_int, 900);
369
370   char fooData[64] = {0};
371   EXPECT_EQ(fooData[0], 0); // suppress gcc warning about fooData not being used
372
373   auto functor = std::bind(
374       [fooData](std::unique_ptr<int>& up) mutable { return ++*up; },
375       std::move(unique_ptr_int));
376
377   EXPECT_EQ(functor(), 901);
378
379   Function<int(void), NEM, sizeof(functor)* S / 2> func = std::move(functor);
380   EXPECT_EQ(
381       func.hasAllocatedMemory(),
382       S < 2 || (NEM == FunctionMoveCtor::NO_THROW &&
383                 !std::is_nothrow_move_constructible<decltype(functor)>::value));
384
385   EXPECT_EQ(func(), 902);
386 }
387 TEST(Function, NonCopyableLambda_T0) {
388   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 0>();
389 }
390 TEST(Function, NonCopyableLambda_N0) {
391   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 0>();
392 }
393 TEST(Function, NonCopyableLambda_T1) {
394   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 1>();
395 }
396 TEST(Function, NonCopyableLambda_N1) {
397   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 1>();
398 }
399 TEST(Function, NonCopyableLambda_T2) {
400   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 2>();
401 }
402 TEST(Function, NonCopyableLambda_N2) {
403   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 2>();
404 }
405 TEST(Function, NonCopyableLambda_T3) {
406   non_copyable_lambda_test<FunctionMoveCtor::MAY_THROW, 3>();
407 }
408 TEST(Function, NonCopyableLambda_N3) {
409   non_copyable_lambda_test<FunctionMoveCtor::NO_THROW, 3>();
410 }
411
412 // TEST =====================================================================
413 // Downsize
414
415 template <FunctionMoveCtor NEM>
416 void downsize_test() {
417   Functor<int, 10> functor;
418
419   // set element 3
420   functor(3, 123);
421   EXPECT_EQ(functor(3), 123);
422
423   // Function with large callable storage area (twice the size of
424   // the functor)
425   Function<int(size_t, int), NEM, sizeof(functor)* 2> func2x =
426       std::move(functor);
427   EXPECT_FALSE(func2x.hasAllocatedMemory());
428   EXPECT_EQ(func2x(3, 200), 123);
429   EXPECT_EQ(func2x(3, 201), 200);
430
431   // Function with sufficient callable storage area (equal to
432   // size of the functor)
433   Function<int(size_t, int), NEM, sizeof(functor)> func1x = std::move(func2x);
434   EXPECT_THROW(func2x(0, 0), std::bad_function_call);
435   EXPECT_FALSE(func2x);
436   EXPECT_FALSE(func1x.hasAllocatedMemory());
437   EXPECT_EQ(func1x(3, 202), 201);
438   EXPECT_EQ(func1x(3, 203), 202);
439
440   // Function with minimal callable storage area (functor does
441   // not fit and will be moved to memory on the heap)
442   Function<int(size_t, int), NEM, 0> func0x = std::move(func1x);
443   EXPECT_THROW(func1x(0, 0), std::bad_function_call);
444   EXPECT_FALSE(func1x);
445   EXPECT_TRUE(func0x.hasAllocatedMemory());
446   EXPECT_EQ(func0x(3, 204), 203);
447   EXPECT_EQ(func0x(3, 205), 204);
448
449   // bonus test: move to Function with opposite NoExceptMovable
450   // setting
451   Function<
452       int(size_t, int),
453       NEM == FunctionMoveCtor::NO_THROW ? FunctionMoveCtor::MAY_THROW
454                                         : FunctionMoveCtor::NO_THROW,
455       0>
456       funcnot = std::move(func0x);
457   EXPECT_THROW(func0x(0, 0), std::bad_function_call);
458   EXPECT_FALSE(func0x);
459   EXPECT_TRUE(funcnot.hasAllocatedMemory());
460   EXPECT_EQ(funcnot(3, 206), 205);
461   EXPECT_EQ(funcnot(3, 207), 206);
462 }
463 TEST(Function, Downsize_T) {
464   downsize_test<FunctionMoveCtor::MAY_THROW>();
465 }
466 TEST(Function, Downsize_N) {
467   downsize_test<FunctionMoveCtor::NO_THROW>();
468 }
469
470 // TEST =====================================================================
471 // Refcount
472
473 template <FunctionMoveCtor NEM>
474 void refcount_test() {
475   Functor<int, 100> functor;
476   functor(3, 999);
477   auto shared_int = std::make_shared<int>(100);
478
479   EXPECT_EQ(*shared_int, 100);
480   EXPECT_EQ(shared_int.use_count(), 1);
481
482   Function<int(void), NEM> func1 = [shared_int]() { return ++*shared_int; };
483   EXPECT_EQ(shared_int.use_count(), 2);
484   EXPECT_EQ(func1(), 101);
485   EXPECT_EQ(*shared_int, 101);
486
487   // func2: made to not fit functor.
488   Function<int(void), NEM, sizeof(functor) / 2> func2 = std::move(func1);
489   EXPECT_THROW(func1(), std::bad_function_call);
490   EXPECT_EQ(shared_int.use_count(), 2);
491   EXPECT_FALSE(func1);
492   EXPECT_EQ(func2(), 102);
493   EXPECT_EQ(*shared_int, 102);
494
495   func2 = [shared_int]() { return ++*shared_int; };
496   EXPECT_EQ(shared_int.use_count(), 2);
497   EXPECT_EQ(func2(), 103);
498   EXPECT_EQ(*shared_int, 103);
499
500   // We set func2 to a lambda that captures 'functor', which forces it on
501   // the heap
502   func2 = [functor]() { return functor(3); };
503   EXPECT_TRUE(func2.hasAllocatedMemory());
504   EXPECT_EQ(func2(), 999);
505   EXPECT_EQ(shared_int.use_count(), 1);
506   EXPECT_EQ(*shared_int, 103);
507
508   func2 = [shared_int]() { return ++*shared_int; };
509   EXPECT_EQ(shared_int.use_count(), 2);
510   EXPECT_EQ(func2(), 104);
511   EXPECT_EQ(*shared_int, 104);
512
513   // We set func2 to function pointer, which always fits into the
514   // Function object and is no-except-movable
515   func2 = &func_int_return_987;
516   EXPECT_FALSE(func2.hasAllocatedMemory());
517   EXPECT_EQ(func2(), 987);
518   EXPECT_EQ(shared_int.use_count(), 1);
519   EXPECT_EQ(*shared_int, 104);
520 }
521 TEST(Function, Refcount_T) {
522   refcount_test<FunctionMoveCtor::MAY_THROW>();
523 }
524 TEST(Function, Refcount_N) {
525   refcount_test<FunctionMoveCtor::NO_THROW>();
526 }
527
528 // TEST =====================================================================
529 // Target
530
531 template <FunctionMoveCtor NEM>
532 void target_test() {
533   std::function<int(int)> func = [](int x) { return x + 25; };
534   EXPECT_EQ(func(100), 125);
535
536   Function<int(int), NEM> ufunc = std::move(func);
537   EXPECT_THROW(func(0), std::bad_function_call);
538   EXPECT_EQ(ufunc(200), 225);
539
540   EXPECT_EQ(ufunc.target_type(), typeid(std::function<int(int)>));
541
542   EXPECT_FALSE(ufunc.template target<int>());
543   EXPECT_FALSE(ufunc.template target<std::function<void(void)>>());
544
545   std::function<int(int)>& ufunc_target =
546       *ufunc.template target<std::function<int(int)>>();
547
548   EXPECT_EQ(ufunc_target(300), 325);
549 }
550
551 TEST(Function, Target_T) {
552   target_test<FunctionMoveCtor::MAY_THROW>();
553 }
554 TEST(Function, Target_N) {
555   target_test<FunctionMoveCtor::NO_THROW>();
556 }
557
558 // TEST =====================================================================
559 // OverloadedFunctor
560
561 TEST(Function, OverloadedFunctor) {
562   struct OverloadedFunctor {
563     // variant 1
564     int operator()(int x) {
565       return 100 + 1 * x;
566     }
567
568     // variant 2 (const-overload of v1)
569     int operator()(int x) const {
570       return 100 + 2 * x;
571     }
572
573     // variant 3
574     int operator()(int x, int) {
575       return 100 + 3 * x;
576     }
577
578     // variant 4 (const-overload of v3)
579     int operator()(int x, int) const {
580       return 100 + 4 * x;
581     }
582
583     // variant 5 (non-const, has no const-overload)
584     int operator()(int x, char const*) {
585       return 100 + 5 * x;
586     }
587
588     // variant 6 (const only)
589     int operator()(int x, std::vector<int> const&) const {
590       return 100 + 6 * x;
591     }
592   };
593   OverloadedFunctor of;
594
595   Function<int(int)> variant1 = of;
596   EXPECT_EQ(variant1(15), 100 + 1 * 15);
597
598   Function<int(int) const> variant2 = of;
599   EXPECT_EQ(variant2(16), 100 + 2 * 16);
600
601   Function<int(int, int)> variant3 = of;
602   EXPECT_EQ(variant3(17, 0), 100 + 3 * 17);
603
604   Function<int(int, int) const> variant4 = of;
605   EXPECT_EQ(variant4(18, 0), 100 + 4 * 18);
606
607   Function<int(int, char const*)> variant5 = of;
608   EXPECT_EQ(variant5(19, "foo"), 100 + 5 * 19);
609
610   Function<int(int, std::vector<int> const&)> variant6 = of;
611   EXPECT_EQ(variant6(20, {}), 100 + 6 * 20);
612   EXPECT_EQ(variant6(20, {1, 2, 3}), 100 + 6 * 20);
613
614   Function<int(int, std::vector<int> const&) const> variant6const = of;
615   EXPECT_EQ(variant6const(21, {}), 100 + 6 * 21);
616
617   // Cast const-functions to non-const and the other way around: if the functor
618   // has both const and non-const operator()s for a given parameter signature,
619   // constructing a Function must select one of them, depending on
620   // whether the function type template parameter is const-qualified or not.
621   // When the const-ness is later changed (by moving the
622   // Function<R(Args...)const> into a Function<R(Args...)> or by
623   // calling the folly::constCastFunction which moves it into a
624   // Function<R(Args...)const>), the Function must still execute
625   // the initially selected function.
626
627   auto variant1_const = folly::constCastFunction(std::move(variant1));
628   EXPECT_THROW(variant1(0), std::bad_function_call);
629   EXPECT_EQ(variant1_const(22), 100 + 1 * 22);
630
631   Function<int(int)> variant2_nonconst = std::move(variant2);
632   EXPECT_THROW(variant2(0), std::bad_function_call);
633   EXPECT_EQ(variant2_nonconst(23), 100 + 2 * 23);
634
635   auto variant3_const = folly::constCastFunction(std::move(variant3));
636   EXPECT_THROW(variant3(0, 0), std::bad_function_call);
637   EXPECT_EQ(variant3_const(24, 0), 100 + 3 * 24);
638
639   Function<int(int, int)> variant4_nonconst = std::move(variant4);
640   EXPECT_THROW(variant4(0, 0), std::bad_function_call);
641   EXPECT_EQ(variant4_nonconst(25, 0), 100 + 4 * 25);
642
643   auto variant5_const = folly::constCastFunction(std::move(variant5));
644   EXPECT_THROW(variant5(0, ""), std::bad_function_call);
645   EXPECT_EQ(variant5_const(26, "foo"), 100 + 5 * 26);
646
647   auto variant6_const = folly::constCastFunction(std::move(variant6));
648   EXPECT_THROW(variant6(0, {}), std::bad_function_call);
649   EXPECT_EQ(variant6_const(27, {}), 100 + 6 * 27);
650
651   Function<int(int, std::vector<int> const&)> variant6const_nonconst =
652       std::move(variant6const);
653   EXPECT_THROW(variant6const(0, {}), std::bad_function_call);
654   EXPECT_EQ(variant6const_nonconst(28, {}), 100 + 6 * 28);
655 }
656
657 // TEST =====================================================================
658 // Lambda
659
660 TEST(Function, Lambda) {
661   // Non-mutable lambdas: can be stored in a non-const...
662   Function<int(int)> func = [](int x) { return 1000 + x; };
663   EXPECT_EQ(func(1), 1001);
664
665   // ...as well as in a const Function
666   Function<int(int) const> func_const = [](int x) { return 2000 + x; };
667   EXPECT_EQ(func_const(1), 2001);
668
669   // Mutable lambda: can only be stored in a const Function:
670   int number = 3000;
671   Function<int()> func_mutable = [number]() mutable { return ++number; };
672   EXPECT_EQ(func_mutable(), 3001);
673   EXPECT_EQ(func_mutable(), 3002);
674
675   // test after const-casting
676
677   Function<int(int) const> func_made_const =
678       folly::constCastFunction(std::move(func));
679   EXPECT_EQ(func_made_const(2), 1002);
680   EXPECT_THROW(func(0), std::bad_function_call);
681
682   Function<int(int)> func_const_made_nonconst = std::move(func_const);
683   EXPECT_EQ(func_const_made_nonconst(2), 2002);
684   EXPECT_THROW(func_const(0), std::bad_function_call);
685
686   Function<int() const> func_mutable_made_const =
687       folly::constCastFunction(std::move(func_mutable));
688   EXPECT_EQ(func_mutable_made_const(), 3003);
689   EXPECT_EQ(func_mutable_made_const(), 3004);
690   EXPECT_THROW(func_mutable(), std::bad_function_call);
691 }
692
693 // TEST =====================================================================
694 // DataMember & MemberFunction
695
696 struct MemberFunc {
697   int x;
698   int getX() const {
699     return x;
700   }
701   void setX(int xx) {
702     x = xx;
703   }
704 };
705
706 TEST(Function, DataMember) {
707   MemberFunc mf;
708   MemberFunc const& cmf = mf;
709   mf.x = 123;
710
711   Function<int(MemberFunc const*)> data_getter1 = &MemberFunc::x;
712   EXPECT_EQ(data_getter1(&cmf), 123);
713   Function<int(MemberFunc*)> data_getter2 = &MemberFunc::x;
714   EXPECT_EQ(data_getter2(&mf), 123);
715   Function<int(MemberFunc const&)> data_getter3 = &MemberFunc::x;
716   EXPECT_EQ(data_getter3(cmf), 123);
717   Function<int(MemberFunc&)> data_getter4 = &MemberFunc::x;
718   EXPECT_EQ(data_getter4(mf), 123);
719 }
720
721 TEST(Function, MemberFunction) {
722   MemberFunc mf;
723   MemberFunc const& cmf = mf;
724   mf.x = 123;
725
726   Function<int(MemberFunc const*)> getter1 = &MemberFunc::getX;
727   EXPECT_EQ(getter1(&cmf), 123);
728   Function<int(MemberFunc*)> getter2 = &MemberFunc::getX;
729   EXPECT_EQ(getter2(&mf), 123);
730   Function<int(MemberFunc const&)> getter3 = &MemberFunc::getX;
731   EXPECT_EQ(getter3(cmf), 123);
732   Function<int(MemberFunc&)> getter4 = &MemberFunc::getX;
733   EXPECT_EQ(getter4(mf), 123);
734
735   Function<void(MemberFunc*, int)> setter1 = &MemberFunc::setX;
736   setter1(&mf, 234);
737   EXPECT_EQ(mf.x, 234);
738
739   Function<void(MemberFunc&, int)> setter2 = &MemberFunc::setX;
740   setter2(mf, 345);
741   EXPECT_EQ(mf.x, 345);
742 }
743
744 // TEST =====================================================================
745 // CaptureCopyMoveCount & ParameterCopyMoveCount
746
747 class CopyMoveTracker {
748  public:
749   struct ConstructorTag {};
750
751   CopyMoveTracker() = delete;
752   explicit CopyMoveTracker(ConstructorTag)
753       : data_(std::make_shared<std::pair<size_t, size_t>>(0, 0)) {}
754
755   CopyMoveTracker(CopyMoveTracker const& o) noexcept : data_(o.data_) {
756     ++data_->first;
757   }
758   CopyMoveTracker& operator=(CopyMoveTracker const& o) noexcept {
759     data_ = o.data_;
760     ++data_->first;
761     return *this;
762   }
763
764   CopyMoveTracker(CopyMoveTracker&& o) noexcept : data_(o.data_) {
765     ++data_->second;
766   }
767   CopyMoveTracker& operator=(CopyMoveTracker&& o) noexcept {
768     data_ = o.data_;
769     ++data_->second;
770     return *this;
771   }
772
773   size_t copyCount() const {
774     return data_->first;
775   }
776   size_t moveCount() const {
777     return data_->second;
778   }
779   size_t refCount() const {
780     return data_.use_count();
781   }
782   void resetCounters() {
783     data_->first = data_->second = 0;
784   }
785
786  private:
787   // copy, move
788   std::shared_ptr<std::pair<size_t, size_t>> data_;
789 };
790
791 TEST(Function, CaptureCopyMoveCount) {
792   // This test checks that no unnecessary copies/moves are made.
793
794   CopyMoveTracker cmt(CopyMoveTracker::ConstructorTag{});
795   EXPECT_EQ(cmt.copyCount(), 0);
796   EXPECT_EQ(cmt.moveCount(), 0);
797   EXPECT_EQ(cmt.refCount(), 1);
798
799   // Move into lambda, move lambda into Function
800   auto lambda1 = [cmt = std::move(cmt)]() {
801     return cmt.moveCount();
802   };
803   Function<size_t(void)> uf1 = std::move(lambda1);
804
805   // Max copies: 0. Max copy+moves: 2.
806   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
807   EXPECT_LE(cmt.copyCount(), 0);
808
809   cmt.resetCounters();
810
811   // Move into lambda, copy lambda into Function
812   auto lambda2 = [cmt = std::move(cmt)]() {
813     return cmt.moveCount();
814   };
815   Function<size_t(void)> uf2 = lambda2;
816
817   // Max copies: 1. Max copy+moves: 2.
818   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
819   EXPECT_LE(cmt.copyCount(), 1);
820
821   // Invoking Function must not make copies/moves of the callable
822   cmt.resetCounters();
823   uf1();
824   uf2();
825   EXPECT_EQ(cmt.copyCount(), 0);
826   EXPECT_EQ(cmt.moveCount(), 0);
827 }
828
829 TEST(Function, ParameterCopyMoveCount) {
830   // This test checks that no unnecessary copies/moves are made.
831
832   CopyMoveTracker cmt(CopyMoveTracker::ConstructorTag{});
833   EXPECT_EQ(cmt.copyCount(), 0);
834   EXPECT_EQ(cmt.moveCount(), 0);
835   EXPECT_EQ(cmt.refCount(), 1);
836
837   // pass by value
838   Function<size_t(CopyMoveTracker)> uf1 = [](CopyMoveTracker c) {
839     return c.moveCount();
840   };
841
842   cmt.resetCounters();
843   uf1(cmt);
844   // Max copies: 1. Max copy+moves: 2.
845   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
846   EXPECT_LE(cmt.copyCount(), 1);
847
848   cmt.resetCounters();
849   uf1(std::move(cmt));
850   // Max copies: 1. Max copy+moves: 2.
851   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 2);
852   EXPECT_LE(cmt.copyCount(), 0);
853
854   // pass by reference
855   Function<size_t(CopyMoveTracker&)> uf2 = [](CopyMoveTracker& c) {
856     return c.moveCount();
857   };
858
859   cmt.resetCounters();
860   uf2(cmt);
861   // Max copies: 0. Max copy+moves: 0.
862   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
863   EXPECT_LE(cmt.copyCount(), 0);
864
865   // pass by const reference
866   Function<size_t(CopyMoveTracker const&)> uf3 = [](CopyMoveTracker const& c) {
867     return c.moveCount();
868   };
869
870   cmt.resetCounters();
871   uf3(cmt);
872   // Max copies: 0. Max copy+moves: 0.
873   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
874   EXPECT_LE(cmt.copyCount(), 0);
875
876   // pass by rvalue reference
877   Function<size_t(CopyMoveTracker &&)> uf4 = [](CopyMoveTracker&& c) {
878     return c.moveCount();
879   };
880
881   cmt.resetCounters();
882   uf4(std::move(cmt));
883   // Max copies: 0. Max copy+moves: 0.
884   EXPECT_LE(cmt.moveCount() + cmt.copyCount(), 0);
885   EXPECT_LE(cmt.copyCount(), 0);
886 }
887
888 // TEST =====================================================================
889 // CopyMoveThrows
890
891 enum ExceptionType { COPY, MOVE };
892
893 template <ExceptionType ET>
894 class CopyMoveException : public std::runtime_error {
895  public:
896   using std::runtime_error::runtime_error;
897 };
898
899 template <bool CopyThrows, bool MoveThrows>
900 struct CopyMoveThrowsCallable {
901   int allowCopyOperations{0};
902   int allowMoveOperations{0};
903
904   CopyMoveThrowsCallable() = default;
905   CopyMoveThrowsCallable(CopyMoveThrowsCallable const& o) noexcept(
906       !CopyThrows) {
907     *this = o;
908   }
909   CopyMoveThrowsCallable& operator=(CopyMoveThrowsCallable const& o) noexcept(
910       !CopyThrows) {
911     allowCopyOperations = o.allowCopyOperations;
912     allowMoveOperations = o.allowMoveOperations;
913
914     if (allowCopyOperations > 0) {
915       --allowCopyOperations;
916     } else if (CopyThrows) {
917       throw CopyMoveException<COPY>("CopyMoveThrowsCallable copy");
918     }
919     return *this;
920   }
921   CopyMoveThrowsCallable(CopyMoveThrowsCallable&& o) noexcept(!MoveThrows) {
922     *this = std::move(o);
923   }
924   CopyMoveThrowsCallable& operator=(CopyMoveThrowsCallable&& o) noexcept(
925       !MoveThrows) {
926     allowCopyOperations = o.allowCopyOperations;
927     allowMoveOperations = o.allowMoveOperations;
928
929     if (o.allowMoveOperations > 0) {
930       --allowMoveOperations;
931     } else if (MoveThrows) {
932       throw CopyMoveException<MOVE>("CopyMoveThrowsCallable move");
933     }
934     return *this;
935   }
936
937   void operator()() const {}
938 };
939
940 TEST(Function, CopyMoveThrowsCallable) {
941   EXPECT_TRUE((std::is_nothrow_move_constructible<
942                CopyMoveThrowsCallable<false, false>>::value));
943   EXPECT_TRUE((std::is_nothrow_move_constructible<
944                CopyMoveThrowsCallable<true, false>>::value));
945   EXPECT_FALSE((std::is_nothrow_move_constructible<
946                 CopyMoveThrowsCallable<false, true>>::value));
947   EXPECT_FALSE((std::is_nothrow_move_constructible<
948                 CopyMoveThrowsCallable<true, true>>::value));
949
950   EXPECT_TRUE((std::is_nothrow_copy_constructible<
951                CopyMoveThrowsCallable<false, false>>::value));
952   EXPECT_FALSE((std::is_nothrow_copy_constructible<
953                 CopyMoveThrowsCallable<true, false>>::value));
954   EXPECT_TRUE((std::is_nothrow_copy_constructible<
955                CopyMoveThrowsCallable<false, true>>::value));
956   EXPECT_FALSE((std::is_nothrow_copy_constructible<
957                 CopyMoveThrowsCallable<true, true>>::value));
958 }
959
960 template <FunctionMoveCtor NEM, bool CopyThrows, bool MoveThrows>
961 void copy_and_move_throws_test() {
962   CopyMoveThrowsCallable<CopyThrows, MoveThrows> c;
963   Function<void(void), NEM> uf;
964
965   if (CopyThrows) {
966     EXPECT_THROW((uf = c), CopyMoveException<COPY>);
967   } else {
968     EXPECT_NO_THROW((uf = c));
969   }
970
971   if (MoveThrows) {
972     EXPECT_THROW((uf = std::move(c)), CopyMoveException<MOVE>);
973   } else {
974     EXPECT_NO_THROW((uf = std::move(c)));
975   }
976
977   c.allowMoveOperations = 1;
978   uf = std::move(c);
979   if (NEM == FunctionMoveCtor::MAY_THROW && MoveThrows) {
980     Function<void(void), NEM> uf2;
981     EXPECT_THROW((uf2 = std::move(uf)), CopyMoveException<MOVE>);
982   } else {
983     Function<void(void), NEM> uf2;
984     EXPECT_NO_THROW((uf2 = std::move(uf)));
985   }
986
987   c.allowMoveOperations = 0;
988   c.allowCopyOperations = 1;
989   uf = c;
990   if (NEM == FunctionMoveCtor::MAY_THROW && MoveThrows) {
991     Function<void(void), NEM> uf2;
992     EXPECT_THROW((uf2 = std::move(uf)), CopyMoveException<MOVE>);
993   } else {
994     Function<void(void), NEM> uf2;
995     EXPECT_NO_THROW((uf2 = std::move(uf)));
996   }
997 }
998
999 TEST(Function, CopyAndMoveThrows_TNN) {
1000   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, false, false>();
1001 }
1002
1003 TEST(Function, CopyAndMoveThrows_NNN) {
1004   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, false, false>();
1005 }
1006
1007 TEST(Function, CopyAndMoveThrows_TTN) {
1008   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, true, false>();
1009 }
1010
1011 TEST(Function, CopyAndMoveThrows_NTN) {
1012   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, true, false>();
1013 }
1014
1015 TEST(Function, CopyAndMoveThrows_TNT) {
1016   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, false, true>();
1017 }
1018
1019 TEST(Function, CopyAndMoveThrows_NNT) {
1020   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, false, true>();
1021 }
1022
1023 TEST(Function, CopyAndMoveThrows_TTT) {
1024   copy_and_move_throws_test<FunctionMoveCtor::MAY_THROW, true, true>();
1025 }
1026
1027 TEST(Function, CopyAndMoveThrows_NTT) {
1028   copy_and_move_throws_test<FunctionMoveCtor::NO_THROW, true, true>();
1029 }
1030
1031 // TEST =====================================================================
1032 // VariadicTemplate & VariadicArguments
1033
1034 struct VariadicTemplateSum {
1035   int operator()() const {
1036     return 0;
1037   }
1038   template <class... Args>
1039   int operator()(int x, Args... args) const {
1040     return x + (*this)(args...);
1041   }
1042 };
1043
1044 TEST(Function, VariadicTemplate) {
1045   Function<int(int)> uf1 = VariadicTemplateSum();
1046   Function<int(int, int)> uf2 = VariadicTemplateSum();
1047   Function<int(int, int, int)> uf3 = VariadicTemplateSum();
1048
1049   EXPECT_EQ(uf1(66), 66);
1050   EXPECT_EQ(uf2(55, 44), 99);
1051   EXPECT_EQ(uf3(33, 22, 11), 66);
1052 }
1053
1054 struct VariadicArgumentsSum {
1055   int operator()(int count, ...) const {
1056     int result = 0;
1057     va_list args;
1058     va_start(args, count);
1059     for (int i = 0; i < count; ++i) {
1060       result += va_arg(args, int);
1061     }
1062     va_end(args);
1063     return result;
1064   }
1065 };
1066
1067 TEST(Function, VariadicArguments) {
1068   Function<int(int)> uf1 = VariadicArgumentsSum();
1069   Function<int(int, int)> uf2 = VariadicArgumentsSum();
1070   Function<int(int, int, int)> uf3 = VariadicArgumentsSum();
1071
1072   EXPECT_EQ(uf1(0), 0);
1073   EXPECT_EQ(uf2(1, 66), 66);
1074   EXPECT_EQ(uf3(2, 55, 44), 99);
1075 }
1076
1077 // TEST =====================================================================
1078 // SafeCaptureByReference
1079
1080 // A function can use Function const& as a parameter to signal that it
1081 // is safe to pass a lambda that captures local variables by reference.
1082 // It is safe because we know the function called can only invoke the
1083 // Function until it returns. It can't store a copy of the Function
1084 // (because it's not copyable), and it can't move the Function somewhere
1085 // else (because it gets only a const&).
1086
1087 template <typename T>
1088 void for_each(
1089     T const& range,
1090     Function<void(typename T::value_type const&) const> const& func) {
1091   for (auto const& elem : range) {
1092     func(elem);
1093   }
1094 }
1095
1096 TEST(Function, SafeCaptureByReference) {
1097   std::vector<int> const vec = {20, 30, 40, 2, 3, 4, 200, 300, 400};
1098
1099   int sum = 0;
1100
1101   // for_each's second parameter is of type Function<...> const&.
1102   // Hence we know we can safely pass it a lambda that references local
1103   // variables. There is no way the reference to x will be stored anywhere.
1104   for_each<std::vector<int>>(vec, [&sum](int x) { sum += x; });
1105
1106   // gcc versions before 4.9 cannot deduce the type T in the above call
1107   // to for_each. Modern compiler versions can compile the following line:
1108   //   for_each(vec, [&sum](int x) { sum += x; });
1109
1110   EXPECT_EQ(sum, 999);
1111 }
1112
1113 // TEST =====================================================================
1114 // IgnoreReturnValue
1115
1116 TEST(Function, IgnoreReturnValue) {
1117   int x = 95;
1118
1119   // Assign a lambda that return int to a folly::Function that returns void.
1120   Function<void()> f = [&]() -> int { return ++x; };
1121
1122   EXPECT_EQ(x, 95);
1123   f();
1124   EXPECT_EQ(x, 96);
1125
1126   Function<int()> g = [&]() -> int { return ++x; };
1127   Function<void()> cg = std::move(g);
1128
1129   EXPECT_EQ(x, 96);
1130   cg();
1131   EXPECT_EQ(x, 97);
1132 }
1133
1134 // TEST =====================================================================
1135 // ReturnConvertible, ConvertReturnType
1136
1137 TEST(Function, ReturnConvertible) {
1138   struct CBase {
1139     int x;
1140   };
1141   struct CDerived : CBase {};
1142
1143   Function<double()> f1 = []() -> int { return 5; };
1144   EXPECT_EQ(f1(), 5.0);
1145
1146   Function<int()> f2 = []() -> double { return 5.2; };
1147   EXPECT_EQ(f2(), 5);
1148
1149   CDerived derived;
1150   derived.x = 55;
1151
1152   Function<CBase const&()> f3 = [&]() -> CDerived const& { return derived; };
1153   EXPECT_EQ(f3().x, 55);
1154
1155   Function<CBase const&()> f4 = [&]() -> CDerived& { return derived; };
1156   EXPECT_EQ(f4().x, 55);
1157
1158   Function<CBase&()> f5 = [&]() -> CDerived& { return derived; };
1159   EXPECT_EQ(f5().x, 55);
1160
1161   Function<CBase const*()> f6 = [&]() -> CDerived const* { return &derived; };
1162   EXPECT_EQ(f6()->x, 55);
1163
1164   Function<CBase const*()> f7 = [&]() -> CDerived* { return &derived; };
1165   EXPECT_EQ(f7()->x, 55);
1166
1167   Function<CBase*()> f8 = [&]() -> CDerived* { return &derived; };
1168   EXPECT_EQ(f8()->x, 55);
1169
1170   Function<CBase()> f9 = [&]() -> CDerived {
1171     auto d = derived;
1172     d.x = 66;
1173     return d;
1174   };
1175   EXPECT_EQ(f9().x, 66);
1176 }
1177
1178 TEST(Function, ConvertReturnType) {
1179   struct CBase {
1180     int x;
1181   };
1182   struct CDerived : CBase {};
1183
1184   Function<int()> f1 = []() -> int { return 5; };
1185   Function<double()> cf1 = std::move(f1);
1186   EXPECT_EQ(cf1(), 5.0);
1187   Function<int()> ccf1 = std::move(cf1);
1188   EXPECT_EQ(ccf1(), 5);
1189
1190   Function<double()> f2 = []() -> double { return 5.2; };
1191   Function<int()> cf2 = std::move(f2);
1192   EXPECT_EQ(cf2(), 5);
1193   Function<double()> ccf2 = std::move(cf2);
1194   EXPECT_EQ(ccf2(), 5.0);
1195
1196   CDerived derived;
1197   derived.x = 55;
1198
1199   Function<CDerived const&()> f3 = [&]() -> CDerived const& { return derived; };
1200   Function<CBase const&()> cf3 = std::move(f3);
1201   EXPECT_EQ(cf3().x, 55);
1202
1203   Function<CDerived&()> f4 = [&]() -> CDerived& { return derived; };
1204   Function<CBase const&()> cf4 = std::move(f4);
1205   EXPECT_EQ(cf4().x, 55);
1206
1207   Function<CDerived&()> f5 = [&]() -> CDerived& { return derived; };
1208   Function<CBase&()> cf5 = std::move(f5);
1209   EXPECT_EQ(cf5().x, 55);
1210
1211   Function<CDerived const*()> f6 = [&]() -> CDerived const* {
1212     return &derived;
1213   };
1214   Function<CBase const*()> cf6 = std::move(f6);
1215   EXPECT_EQ(cf6()->x, 55);
1216
1217   Function<CDerived const*()> f7 = [&]() -> CDerived* { return &derived; };
1218   Function<CBase const*()> cf7 = std::move(f7);
1219   EXPECT_EQ(cf7()->x, 55);
1220
1221   Function<CDerived*()> f8 = [&]() -> CDerived* { return &derived; };
1222   Function<CBase*()> cf8 = std::move(f8);
1223   EXPECT_EQ(cf8()->x, 55);
1224
1225   Function<CDerived()> f9 = [&]() -> CDerived {
1226     auto d = derived;
1227     d.x = 66;
1228     return d;
1229   };
1230   Function<CBase()> cf9 = std::move(f9);
1231   EXPECT_EQ(cf9().x, 66);
1232 }
1233
1234 TEST(Function, asStdFunction_void) {
1235   int i = 0;
1236   folly::Function<void()> f = [&] { ++i; };
1237   auto sf = std::move(f).asStdFunction();
1238   static_assert(std::is_same<decltype(sf), std::function<void()>>::value,
1239       "std::function has wrong type");
1240   sf();
1241   EXPECT_EQ(1, i);
1242 }
1243
1244 TEST(Function, asStdFunction_void_const) {
1245   int i = 0;
1246   folly::Function<void() const> f = [&] { ++i; };
1247   auto sf = std::move(f).asStdFunction();
1248   static_assert(std::is_same<decltype(sf), std::function<void()>>::value,
1249       "std::function has wrong type");
1250   sf();
1251   EXPECT_EQ(1, i);
1252 }
1253
1254 TEST(Function, asStdFunction_return) {
1255   int i = 0;
1256   folly::Function<int()> f = [&] {
1257     ++i;
1258     return 42;
1259   };
1260   auto sf = std::move(f).asStdFunction();
1261   static_assert(std::is_same<decltype(sf), std::function<int()>>::value,
1262       "std::function has wrong type");
1263   EXPECT_EQ(42, sf());
1264   EXPECT_EQ(1, i);
1265 }
1266
1267 TEST(Function, asStdFunction_return_const) {
1268   int i = 0;
1269   folly::Function<int() const> f = [&] {
1270     ++i;
1271     return 42;
1272   };
1273   auto sf = std::move(f).asStdFunction();
1274   static_assert(std::is_same<decltype(sf), std::function<int()>>::value,
1275       "std::function has wrong type");
1276   EXPECT_EQ(42, sf());
1277   EXPECT_EQ(1, i);
1278 }
1279
1280 TEST(Function, asStdFunction_args) {
1281   int i = 0;
1282   folly::Function<void(int, int)> f = [&](int x, int y) {
1283     ++i;
1284     return x + y;
1285   };
1286   auto sf = std::move(f).asStdFunction();
1287   static_assert(std::is_same<decltype(sf), std::function<void(int, int)>>::value,
1288       "std::function has wrong type");
1289   sf(42, 42);
1290   EXPECT_EQ(1, i);
1291 }
1292
1293 TEST(Function, asStdFunction_args_const) {
1294   int i = 0;
1295   folly::Function<void(int, int) const> f = [&](int x, int y) {
1296     ++i;
1297     return x + y;
1298   };
1299   auto sf = std::move(f).asStdFunction();
1300   static_assert(std::is_same<decltype(sf), std::function<void(int, int)>>::value,
1301       "std::function has wrong type");
1302   sf(42, 42);
1303   EXPECT_EQ(1, i);
1304 }