1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <lib/fit/function.h>
6 #include <unittest/unittest.h>
7
8 namespace {
9
10 using Closure = void();
11 using ClosureWrongReturnType = int();
12 using BinaryOp = int(int a, int b);
13 using BinaryOpWrongReturnType = void(int a, int b);
14 using MoveOp = std::unique_ptr<int>(std::unique_ptr<int> value);
15 using BooleanGenerator = bool();
16 using IntGenerator = int();
17
18 class BuildableFromInt {
19 public:
20 BuildableFromInt(int);
21 BuildableFromInt& operator=(int);
22 };
23
24 using BuildableFromIntGenerator = BuildableFromInt();
25
26 // A big object which causes a function target to be heap allocated.
27 struct Big {
28 int data[64]{};
29 };
30 constexpr size_t HugeCallableSize = sizeof(Big) + sizeof(void*) * 4;
31
32 // An object that looks like an "empty" std::function.
33 template <typename>
34 struct EmptyFunction;
35 template <typename R, typename... Args>
36 struct EmptyFunction<R(Args...)> {
operator ()__anon31b8501e0111::EmptyFunction37 R operator()(Args... args) const { return fptr(args...); }
operator ==__anon31b8501e0111::EmptyFunction38 bool operator==(decltype(nullptr)) const { return true; }
39
40 R(*fptr)
41 (Args...) = nullptr;
42 };
43
44 // An object whose state we can examine from the outside.
45 struct SlotMachine {
operator ()__anon31b8501e0111::SlotMachine46 void operator()() { value++; }
operator ()__anon31b8501e0111::SlotMachine47 int operator()(int a, int b) {
48 value += a * b;
49 return value;
50 }
51
52 int value = 0;
53 };
54
55 // A move-only object which increments a counter when uniquely destroyed.
56 class DestructionObserver {
57 public:
DestructionObserver(int * counter)58 DestructionObserver(int* counter)
59 : counter_(counter) {}
DestructionObserver(DestructionObserver && other)60 DestructionObserver(DestructionObserver&& other)
61 : counter_(other.counter_) {
62 other.counter_ = nullptr;
63 }
64 DestructionObserver(const DestructionObserver& other) = delete;
65
~DestructionObserver()66 ~DestructionObserver() {
67 if (counter_)
68 *counter_ += 1;
69 }
70
71 DestructionObserver& operator=(const DestructionObserver& other) = delete;
operator =(DestructionObserver && other)72 DestructionObserver& operator=(DestructionObserver&& other) {
73 if (counter_)
74 *counter_ += 1;
75 counter_ = other.counter_;
76 other.counter_ = nullptr;
77 return *this;
78 }
79
80 private:
81 int* counter_;
82 };
83
84 template <typename ClosureFunction>
closure()85 bool closure() {
86 static_assert(fit::is_nullable<ClosureFunction>::value, "");
87
88 BEGIN_TEST;
89
90 // default initialization
91 ClosureFunction fdefault;
92 EXPECT_FALSE(!!fdefault);
93
94 // nullptr initialization
95 ClosureFunction fnull(nullptr);
96 EXPECT_FALSE(!!fnull);
97
98 // null function pointer initialization
99 Closure* fptr = nullptr;
100 ClosureFunction ffunc(fptr);
101 EXPECT_FALSE(!!ffunc);
102
103 // "empty std::function" initialization
104 EmptyFunction<Closure> empty;
105 ClosureFunction fwrapper(empty);
106 EXPECT_FALSE(!!fwrapper);
107
108 // inline callable initialization
109 int finline_value = 0;
110 ClosureFunction finline([&finline_value] { finline_value++; });
111 EXPECT_TRUE(!!finline);
112 finline();
113 EXPECT_EQ(1, finline_value);
114 finline();
115 EXPECT_EQ(2, finline_value);
116
117 // heap callable initialization
118 int fheap_value = 0;
119 ClosureFunction fheap([&fheap_value, big = Big()] { fheap_value++; });
120 EXPECT_TRUE(!!fheap);
121 fheap();
122 EXPECT_EQ(1, fheap_value);
123 fheap();
124 EXPECT_EQ(2, fheap_value);
125
126 // move initialization of a nullptr
127 ClosureFunction fnull2(std::move(fnull));
128 EXPECT_FALSE(!!fnull2);
129
130 // move initialization of an inline callable
131 ClosureFunction finline2(std::move(finline));
132 EXPECT_TRUE(!!finline2);
133 EXPECT_FALSE(!!finline);
134 finline2();
135 EXPECT_EQ(3, finline_value);
136 finline2();
137 EXPECT_EQ(4, finline_value);
138
139 // move initialization of a heap callable
140 ClosureFunction fheap2(std::move(fheap));
141 EXPECT_TRUE(!!fheap2);
142 EXPECT_FALSE(!!fheap);
143 fheap2();
144 EXPECT_EQ(3, fheap_value);
145 fheap2();
146 EXPECT_EQ(4, fheap_value);
147
148 // inline mutable lambda
149 int fmutinline_value = 0;
150 ClosureFunction fmutinline([&fmutinline_value, x = 1]() mutable {
151 x *= 2;
152 fmutinline_value = x;
153 });
154 EXPECT_TRUE(!!fmutinline);
155 fmutinline();
156 EXPECT_EQ(2, fmutinline_value);
157 fmutinline();
158 EXPECT_EQ(4, fmutinline_value);
159
160 // heap-allocated mutable lambda
161 int fmutheap_value = 0;
162 ClosureFunction fmutheap([&fmutheap_value, big = Big(), x = 1]() mutable {
163 x *= 2;
164 fmutheap_value = x;
165 });
166 EXPECT_TRUE(!!fmutheap);
167 fmutheap();
168 EXPECT_EQ(2, fmutheap_value);
169 fmutheap();
170 EXPECT_EQ(4, fmutheap_value);
171
172 // move assignment of non-null
173 ClosureFunction fnew([] {});
174 fnew = std::move(finline2);
175 EXPECT_TRUE(!!fnew);
176 fnew();
177 EXPECT_EQ(5, finline_value);
178 fnew();
179 EXPECT_EQ(6, finline_value);
180
181 // move assignment of self
182 fnew = std::move(fnew);
183 EXPECT_TRUE(!!fnew);
184 fnew();
185 EXPECT_EQ(7, finline_value);
186
187 // move assignment of null
188 fnew = std::move(fnull);
189 EXPECT_FALSE(!!fnew);
190
191 // callable assignment with operator=
192 int fnew_value = 0;
193 fnew = [&fnew_value] { fnew_value++; };
194 EXPECT_TRUE(!!fnew);
195 fnew();
196 EXPECT_EQ(1, fnew_value);
197 fnew();
198 EXPECT_EQ(2, fnew_value);
199
200 // nullptr assignment
201 fnew = nullptr;
202 EXPECT_FALSE(!!fnew);
203
204 // swap (currently null)
205 swap(fnew, fheap2);
206 EXPECT_TRUE(!!fnew);
207 EXPECT_FALSE(!!fheap);
208 fnew();
209 EXPECT_EQ(5, fheap_value);
210 fnew();
211 EXPECT_EQ(6, fheap_value);
212
213 // swap with self
214 swap(fnew, fnew);
215 EXPECT_TRUE(!!fnew);
216 fnew();
217 EXPECT_EQ(7, fheap_value);
218 fnew();
219 EXPECT_EQ(8, fheap_value);
220
221 // swap with non-null
222 swap(fnew, fmutinline);
223 EXPECT_TRUE(!!fmutinline);
224 EXPECT_TRUE(!!fnew);
225 fmutinline();
226 EXPECT_EQ(9, fheap_value);
227 fmutinline();
228 EXPECT_EQ(10, fheap_value);
229 fnew();
230 EXPECT_EQ(8, fmutinline_value);
231 fnew();
232 EXPECT_EQ(16, fmutinline_value);
233
234 // nullptr comparison operators
235 EXPECT_TRUE(fnull == nullptr);
236 EXPECT_FALSE(fnull != nullptr);
237 EXPECT_TRUE(nullptr == fnull);
238 EXPECT_FALSE(nullptr != fnull);
239 EXPECT_FALSE(fnew == nullptr);
240 EXPECT_TRUE(fnew != nullptr);
241 EXPECT_FALSE(nullptr == fnew);
242 EXPECT_TRUE(nullptr != fnew);
243
244 // null function pointer assignment
245 fnew = fptr;
246 EXPECT_FALSE(!!fnew);
247
248 // "empty std::function" assignment
249 fmutinline = empty;
250 EXPECT_FALSE(!!fmutinline);
251
252 // target access
253 ClosureFunction fslot;
254 EXPECT_NULL(fslot.template target<decltype(nullptr)>());
255 fslot = SlotMachine{42};
256 fslot();
257 SlotMachine* fslottarget = fslot.template target<SlotMachine>();
258 EXPECT_EQ(43, fslottarget->value);
259 const SlotMachine* fslottargetconst =
260 const_cast<const ClosureFunction&>(fslot).template target<SlotMachine>();
261 EXPECT_EQ(fslottarget, fslottargetconst);
262 fslot = nullptr;
263 EXPECT_NULL(fslot.template target<decltype(nullptr)>());
264
265 END_TEST;
266 }
267
268 template <typename BinaryOpFunction>
binary_op()269 bool binary_op() {
270 static_assert(fit::is_nullable<BinaryOpFunction>::value, "");
271
272 BEGIN_TEST;
273
274 // default initialization
275 BinaryOpFunction fdefault;
276 EXPECT_FALSE(!!fdefault);
277
278 // nullptr initialization
279 BinaryOpFunction fnull(nullptr);
280 EXPECT_FALSE(!!fnull);
281
282 // null function pointer initialization
283 BinaryOp* fptr = nullptr;
284 BinaryOpFunction ffunc(fptr);
285 EXPECT_FALSE(!!ffunc);
286
287 // "empty std::function" initialization
288 EmptyFunction<BinaryOp> empty;
289 BinaryOpFunction fwrapper(empty);
290 EXPECT_FALSE(!!fwrapper);
291
292 // inline callable initialization
293 int finline_value = 0;
294 BinaryOpFunction finline([&finline_value](int a, int b) {
295 finline_value++;
296 return a + b;
297 });
298 EXPECT_TRUE(!!finline);
299 EXPECT_EQ(10, finline(3, 7));
300 EXPECT_EQ(1, finline_value);
301 EXPECT_EQ(10, finline(3, 7));
302 EXPECT_EQ(2, finline_value);
303
304 // heap callable initialization
305 int fheap_value = 0;
306 BinaryOpFunction fheap([&fheap_value, big = Big()](int a, int b) {
307 fheap_value++;
308 return a + b;
309 });
310 EXPECT_TRUE(!!fheap);
311 EXPECT_EQ(10, fheap(3, 7));
312 EXPECT_EQ(1, fheap_value);
313 EXPECT_EQ(10, fheap(3, 7));
314 EXPECT_EQ(2, fheap_value);
315
316 // move initialization of a nullptr
317 BinaryOpFunction fnull2(std::move(fnull));
318 EXPECT_FALSE(!!fnull2);
319
320 // move initialization of an inline callable
321 BinaryOpFunction finline2(std::move(finline));
322 EXPECT_TRUE(!!finline2);
323 EXPECT_FALSE(!!finline);
324 EXPECT_EQ(10, finline2(3, 7));
325 EXPECT_EQ(3, finline_value);
326 EXPECT_EQ(10, finline2(3, 7));
327 EXPECT_EQ(4, finline_value);
328
329 // move initialization of a heap callable
330 BinaryOpFunction fheap2(std::move(fheap));
331 EXPECT_TRUE(!!fheap2);
332 EXPECT_FALSE(!!fheap);
333 EXPECT_EQ(10, fheap2(3, 7));
334 EXPECT_EQ(3, fheap_value);
335 EXPECT_EQ(10, fheap2(3, 7));
336 EXPECT_EQ(4, fheap_value);
337
338 // inline mutable lambda
339 int fmutinline_value = 0;
340 BinaryOpFunction fmutinline([&fmutinline_value, x = 1](int a, int b) mutable {
341 x *= 2;
342 fmutinline_value = x;
343 return a + b;
344 });
345 EXPECT_TRUE(!!fmutinline);
346 EXPECT_EQ(10, fmutinline(3, 7));
347 EXPECT_EQ(2, fmutinline_value);
348 EXPECT_EQ(10, fmutinline(3, 7));
349 EXPECT_EQ(4, fmutinline_value);
350
351 // heap-allocated mutable lambda
352 int fmutheap_value = 0;
353 BinaryOpFunction fmutheap([&fmutheap_value, big = Big(), x = 1](int a, int b) mutable {
354 x *= 2;
355 fmutheap_value = x;
356 return a + b;
357 });
358 EXPECT_TRUE(!!fmutheap);
359 EXPECT_EQ(10, fmutheap(3, 7));
360 EXPECT_EQ(2, fmutheap_value);
361 EXPECT_EQ(10, fmutheap(3, 7));
362 EXPECT_EQ(4, fmutheap_value);
363
364 // move assignment of non-null
365 BinaryOpFunction fnew([](int a, int b) { return 0; });
366 fnew = std::move(finline2);
367 EXPECT_TRUE(!!fnew);
368 EXPECT_EQ(10, fnew(3, 7));
369 EXPECT_EQ(5, finline_value);
370 EXPECT_EQ(10, fnew(3, 7));
371 EXPECT_EQ(6, finline_value);
372
373 // self-assignment of non-null
374 fnew = std::move(fnew);
375 EXPECT_TRUE(!!fnew);
376 EXPECT_EQ(10, fnew(3, 7));
377 EXPECT_EQ(7, finline_value);
378
379 // move assignment of null
380 fnew = std::move(fnull);
381 EXPECT_FALSE(!!fnew);
382
383 // self-assignment of non-null
384 fnew = std::move(fnew);
385 EXPECT_FALSE(!!fnew);
386
387 // callable assignment with operator=
388 int fnew_value = 0;
389 fnew = [&fnew_value](int a, int b) {
390 fnew_value++;
391 return a + b;
392 };
393 EXPECT_TRUE(!!fnew);
394 EXPECT_EQ(10, fnew(3, 7));
395 EXPECT_EQ(1, fnew_value);
396 EXPECT_EQ(10, fnew(3, 7));
397 EXPECT_EQ(2, fnew_value);
398
399 // nullptr assignment
400 fnew = nullptr;
401 EXPECT_FALSE(!!fnew);
402
403 // swap (currently null)
404 swap(fnew, fheap2);
405 EXPECT_TRUE(!!fnew);
406 EXPECT_FALSE(!!fheap);
407 EXPECT_EQ(10, fnew(3, 7));
408 EXPECT_EQ(5, fheap_value);
409 EXPECT_EQ(10, fnew(3, 7));
410 EXPECT_EQ(6, fheap_value);
411
412 // swap with self
413 swap(fnew, fnew);
414 EXPECT_TRUE(!!fnew);
415 EXPECT_EQ(10, fnew(3, 7));
416 EXPECT_EQ(7, fheap_value);
417 EXPECT_EQ(10, fnew(3, 7));
418 EXPECT_EQ(8, fheap_value);
419
420 // swap with non-null
421 swap(fnew, fmutinline);
422 EXPECT_TRUE(!!fmutinline);
423 EXPECT_TRUE(!!fnew);
424 EXPECT_EQ(10, fmutinline(3, 7));
425 EXPECT_EQ(9, fheap_value);
426 EXPECT_EQ(10, fmutinline(3, 7));
427 EXPECT_EQ(10, fheap_value);
428 EXPECT_EQ(10, fnew(3, 7));
429 EXPECT_EQ(8, fmutinline_value);
430 EXPECT_EQ(10, fnew(3, 7));
431 EXPECT_EQ(16, fmutinline_value);
432
433 // nullptr comparison operators
434 EXPECT_TRUE(fnull == nullptr);
435 EXPECT_FALSE(fnull != nullptr);
436 EXPECT_TRUE(nullptr == fnull);
437 EXPECT_FALSE(nullptr != fnull);
438 EXPECT_FALSE(fnew == nullptr);
439 EXPECT_TRUE(fnew != nullptr);
440 EXPECT_FALSE(nullptr == fnew);
441 EXPECT_TRUE(nullptr != fnew);
442
443 // null function pointer assignment
444 fnew = fptr;
445 EXPECT_FALSE(!!fnew);
446
447 // "empty std::function" assignment
448 fmutinline = empty;
449 EXPECT_FALSE(!!fmutinline);
450
451 // target access
452 BinaryOpFunction fslot;
453 EXPECT_NULL(fslot.template target<decltype(nullptr)>());
454 fslot = SlotMachine{42};
455 EXPECT_EQ(54, fslot(3, 4));
456 SlotMachine* fslottarget = fslot.template target<SlotMachine>();
457 EXPECT_EQ(54, fslottarget->value);
458 const SlotMachine* fslottargetconst =
459 const_cast<const BinaryOpFunction&>(fslot).template target<SlotMachine>();
460 EXPECT_EQ(fslottarget, fslottargetconst);
461 fslot = nullptr;
462 EXPECT_NULL(fslot.template target<decltype(nullptr)>());
463
464 END_TEST;
465 }
466
sized_function_size_bounds()467 bool sized_function_size_bounds() {
468 BEGIN_TEST;
469
470 auto empty = [] {};
471 fit::function<Closure, sizeof(empty)> fempty(std::move(empty));
472 static_assert(sizeof(fempty) >= sizeof(empty), "size bounds");
473
474 auto small = [x = 1, y = 2] {
475 (void)x; // suppress unused lambda capture warning
476 (void)y;
477 };
478 fit::function<Closure, sizeof(small)> fsmall(std::move(small));
479 static_assert(sizeof(fsmall) >= sizeof(small), "size bounds");
480 fsmall = [] {};
481
482 auto big = [big = Big(), x = 1] { (void)x; };
483 fit::function<Closure, sizeof(big)> fbig(std::move(big));
484 static_assert(sizeof(fbig) >= sizeof(big), "size bounds");
485 fbig = [x = 1, y = 2] {
486 (void)x;
487 (void)y;
488 };
489 fbig = [] {};
490
491 // These statements do compile though the lambda will be copied to the heap
492 // when they exceed the inline size.
493 fempty = [x = 1, y = 2] {
494 (void)x;
495 (void)y;
496 };
497 fsmall = [big = Big(), x = 1] { (void)x; };
498 fbig = [big = Big(), x = 1, y = 2] {
499 (void)x;
500 (void)y;
501 };
502
503 END_TEST;
504 }
505
inline_function_size_bounds()506 bool inline_function_size_bounds() {
507 BEGIN_TEST;
508
509 auto empty = [] {};
510 fit::inline_function<Closure, sizeof(empty)> fempty(std::move(empty));
511 static_assert(sizeof(fempty) >= sizeof(empty), "size bounds");
512
513 auto small = [x = 1, y = 2] {
514 (void)x; // suppress unused lambda capture warning
515 (void)y;
516 };
517 fit::inline_function<Closure, sizeof(small)> fsmall(std::move(small));
518 static_assert(sizeof(fsmall) >= sizeof(small), "size bounds");
519 fsmall = [] {};
520
521 auto big = [big = Big(), x = 1] { (void)x; };
522 fit::inline_function<Closure, sizeof(big)> fbig(std::move(big));
523 static_assert(sizeof(fbig) >= sizeof(big), "size bounds");
524 fbig = [x = 1, y = 2] {
525 (void)x;
526 (void)y;
527 };
528 fbig = [] {};
529
530 // These statements do not compile because the lambdas are too big to fit.
531 #if 0
532 fempty = [ x = 1, y = 2 ] {
533 (void)x;
534 (void)y;
535 };
536 fsmall = [ big = Big(), x = 1 ] { (void)x; };
537 fbig = [ big = Big(), x = 1, y = 2 ] {
538 (void)x;
539 (void)y;
540 };
541 #endif
542
543 END_TEST;
544 }
545
move_only_argument_and_result()546 bool move_only_argument_and_result() {
547 BEGIN_TEST;
548
549 std::unique_ptr<int> arg(new int());
550 fit::function<MoveOp> f([](std::unique_ptr<int> value) {
551 *value += 1;
552 return value;
553 });
554 arg = f(std::move(arg));
555 EXPECT_EQ(1, *arg);
556 arg = f(std::move(arg));
557 EXPECT_EQ(2, *arg);
558
559 END_TEST;
560 }
561
implicit_construction_helper(fit::closure closure)562 void implicit_construction_helper(fit::closure closure) {}
563
implicit_construction()564 bool implicit_construction() {
565 BEGIN_TEST;
566
567 // ensure we can implicitly construct from nullptr
568 implicit_construction_helper(nullptr);
569
570 // ensure we can implicitly construct from a lambda
571 implicit_construction_helper([] {});
572
573 END_TEST;
574 }
575
arg_count(fit::closure)576 int arg_count(fit::closure) {
577 return 0;
578 }
arg_count(fit::function<void (int)>)579 int arg_count(fit::function<void(int)>) {
580 return 1;
581 }
582
overload_resolution()583 bool overload_resolution() {
584 BEGIN_TEST;
585 EXPECT_EQ(0, arg_count([] {}));
586 EXPECT_EQ(1, arg_count([](int) {}));
587 END_TEST;
588 }
589
590 // We don't have std::shared in Zircon yet.
591 #ifndef FIT_NO_STD_FOR_ZIRCON_USERSPACE
sharing()592 bool sharing() {
593 BEGIN_TEST;
594
595 fit::function<Closure> fnull;
596 fit::function<Closure> fnullshare1 = fnull.share();
597 fit::function<Closure> fnullshare2 = fnull.share();
598 fit::function<Closure> fnullshare3 = fnullshare1.share();
599 EXPECT_FALSE(!!fnull);
600 EXPECT_FALSE(!!fnullshare1);
601 EXPECT_FALSE(!!fnullshare2);
602 EXPECT_FALSE(!!fnullshare3);
603
604 int finlinevalue = 1;
605 int finlinedestroy = 0;
606 fit::function<Closure> finline =
607 [&finlinevalue, d = DestructionObserver(&finlinedestroy)] { finlinevalue++; };
608 fit::function<Closure> finlineshare1 = finline.share();
609 fit::function<Closure> finlineshare2 = finline.share();
610 fit::function<Closure> finlineshare3 = finlineshare1.share();
611 EXPECT_TRUE(!!finline);
612 EXPECT_TRUE(!!finlineshare1);
613 EXPECT_TRUE(!!finlineshare2);
614 EXPECT_TRUE(!!finlineshare3);
615 finline();
616 EXPECT_EQ(2, finlinevalue);
617 finlineshare1();
618 EXPECT_EQ(3, finlinevalue);
619 finlineshare2();
620 EXPECT_EQ(4, finlinevalue);
621 finlineshare3();
622 EXPECT_EQ(5, finlinevalue);
623 finlineshare2();
624 EXPECT_EQ(6, finlinevalue);
625 finline();
626 EXPECT_EQ(7, finlinevalue);
627 EXPECT_EQ(0, finlinedestroy);
628 finline = nullptr;
629 EXPECT_EQ(0, finlinedestroy);
630 finlineshare3 = nullptr;
631 EXPECT_EQ(0, finlinedestroy);
632 finlineshare2 = nullptr;
633 EXPECT_EQ(0, finlinedestroy);
634 finlineshare1 = nullptr;
635 EXPECT_EQ(1, finlinedestroy);
636
637 int fheapvalue = 1;
638 int fheapdestroy = 0;
639 fit::function<Closure> fheap =
640 [&fheapvalue, big = Big(), d = DestructionObserver(&fheapdestroy)] { fheapvalue++; };
641 fit::function<Closure> fheapshare1 = fheap.share();
642 fit::function<Closure> fheapshare2 = fheap.share();
643 fit::function<Closure> fheapshare3 = fheapshare1.share();
644 EXPECT_TRUE(!!fheap);
645 EXPECT_TRUE(!!fheapshare1);
646 EXPECT_TRUE(!!fheapshare2);
647 EXPECT_TRUE(!!fheapshare3);
648 fheap();
649 EXPECT_EQ(2, fheapvalue);
650 fheapshare1();
651 EXPECT_EQ(3, fheapvalue);
652 fheapshare2();
653 EXPECT_EQ(4, fheapvalue);
654 fheapshare3();
655 EXPECT_EQ(5, fheapvalue);
656 fheapshare2();
657 EXPECT_EQ(6, fheapvalue);
658 fheap();
659 EXPECT_EQ(7, fheapvalue);
660 EXPECT_EQ(0, fheapdestroy);
661 fheap = nullptr;
662 EXPECT_EQ(0, fheapdestroy);
663 fheapshare3 = nullptr;
664 EXPECT_EQ(0, fheapdestroy);
665 fheapshare2 = nullptr;
666 EXPECT_EQ(0, fheapdestroy);
667 fheapshare1 = nullptr;
668 EXPECT_EQ(1, fheapdestroy);
669
670 // These statements do not compile because inline functions cannot be shared
671 #if 0
672 fit::inline_function<Closure> fbad;
673 fbad.share();
674 #endif
675
676 END_TEST;
677 }
678 #endif // FIT_NO_STD_FOR_ZIRCON_USERSPACE
679
680 struct Obj {
Call__anon31b8501e0111::Obj681 void Call() {
682 calls++;
683 }
684
AddOne__anon31b8501e0111::Obj685 int AddOne(int x) {
686 calls++;
687 return x + 1;
688 }
689
Sum__anon31b8501e0111::Obj690 int Sum(int a, int b, int c) {
691 calls++;
692 return a + b + c;
693 }
694
AddAndReturn__anon31b8501e0111::Obj695 std::unique_ptr<int> AddAndReturn(std::unique_ptr<int> value) {
696 (*value)++;
697 return value;
698 }
699
700 uint32_t calls = 0;
701 };
702
bind_member()703 bool bind_member() {
704 BEGIN_TEST;
705
706 Obj obj;
707 auto move_only_value = std::make_unique<int>(4);
708
709 fit::bind_member(&obj, &Obj::Call)();
710 EXPECT_EQ(23, fit::bind_member(&obj, &Obj::AddOne)(22));
711 EXPECT_EQ(6, fit::bind_member(&obj, &Obj::Sum)(1, 2, 3));
712 move_only_value = fit::bind_member(&obj, &Obj::AddAndReturn)(std::move(move_only_value));
713 EXPECT_EQ(5, *move_only_value);
714 EXPECT_EQ(3, obj.calls);
715
716 END_TEST;
717 }
718 } // namespace
719
720 namespace test_conversions {
721 static_assert(std::is_convertible<Closure, fit::function<Closure>>::value, "");
722 static_assert(std::is_convertible<BinaryOp, fit::function<BinaryOp>>::value, "");
723 static_assert(std::is_assignable<fit::function<Closure>, Closure>::value, "");
724 static_assert(std::is_assignable<fit::function<BinaryOp>, BinaryOp>::value, "");
725
726 static_assert(std::is_assignable<fit::function<BooleanGenerator>, IntGenerator>::value, "");
727 static_assert(std::is_assignable<fit::function<BuildableFromIntGenerator>, IntGenerator>::value, "");
728 static_assert(!std::is_assignable<fit::function<IntGenerator>, BuildableFromIntGenerator>::value, "");
729
730 static_assert(!std::is_convertible<BinaryOp, fit::function<Closure>>::value, "");
731 static_assert(!std::is_convertible<Closure, fit::function<BinaryOp>>::value, "");
732 static_assert(!std::is_assignable<fit::function<Closure>, BinaryOp>::value, "");
733 static_assert(!std::is_assignable<fit::function<BinaryOp>, Closure>::value, "");
734
735 static_assert(!std::is_convertible<ClosureWrongReturnType,
736 fit::function<Closure>>::value,
737 "");
738 static_assert(!std::is_convertible<BinaryOpWrongReturnType,
739 fit::function<BinaryOp>>::value,
740 "");
741 static_assert(!std::is_assignable<fit::function<Closure>,
742 ClosureWrongReturnType>::value,
743 "");
744 static_assert(!std::is_assignable<fit::function<BinaryOp>,
745 BinaryOpWrongReturnType>::value,
746 "");
747
748 static_assert(!std::is_convertible<void, fit::function<Closure>>::value, "");
749 static_assert(!std::is_convertible<void, fit::function<BinaryOp>>::value, "");
750 static_assert(!std::is_assignable<void, fit::function<Closure>>::value, "");
751 static_assert(!std::is_assignable<void, fit::function<BinaryOp>>::value, "");
752 } // namespace test_conversions
753
754 BEGIN_TEST_CASE(function_tests)
755 RUN_TEST((closure<fit::function<Closure>>))
756 RUN_TEST((binary_op<fit::function<BinaryOp>>))
757 RUN_TEST((closure<fit::function<Closure, 0u>>))
758 RUN_TEST((binary_op<fit::function<BinaryOp, 0u>>))
759 RUN_TEST((closure<fit::function<Closure, HugeCallableSize>>))
760 RUN_TEST((binary_op<fit::function<BinaryOp, HugeCallableSize>>))
761 RUN_TEST((closure<fit::inline_function<Closure, HugeCallableSize>>))
762 RUN_TEST((binary_op<fit::inline_function<BinaryOp, HugeCallableSize>>))
763 RUN_TEST(sized_function_size_bounds);
764 RUN_TEST(inline_function_size_bounds);
765 RUN_TEST(move_only_argument_and_result);
766 RUN_TEST(implicit_construction);
767 RUN_TEST(overload_resolution);
768 #ifndef FIT_NO_STD_FOR_ZIRCON_USERSPACE
769 RUN_TEST(sharing)
770 #endif
771 RUN_TEST(bind_member);
772 END_TEST_CASE(function_tests)
773