xref: /aosp_15_r20/external/pigweed/third_party/fuchsia/repo/sdk/lib/fit/test/function_tests.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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 <lib/stdcompat/bit.h>
7 
8 #include <algorithm>
9 #include <array>
10 #include <cstddef>
11 #include <cstdint>
12 #include <memory>
13 #include <type_traits>
14 
15 #include "gtest/gtest.h"
16 
17 #include "pw_polyfill/language_feature_macros.h"
18 
19 namespace {
20 
21 using ::std::size_t;
22 
23 using Closure = void();
24 using ClosureWrongReturnType = int();
25 using BinaryOp = int(int a, int b);
26 using BinaryOpWrongReturnType = void(int a, int b);
27 using MoveOp = std::unique_ptr<int>(std::unique_ptr<int> value);
28 using BooleanGenerator = bool();
29 using IntGenerator = int();
30 
31 class BuildableFromInt {
32  public:
33   BuildableFromInt(int);
34   BuildableFromInt& operator=(int);
35 };
36 
37 using BuildableFromIntGenerator = BuildableFromInt();
38 
39 // A big object which causes a function target to be heap allocated.
40 struct Big {
41   int data[64]{};
42 };
43 // An object with a very large alignment requirement that cannot be placed in a
44 // fit::inline_function.
45 struct alignas(64) BigAlignment {
46   int data[64]{};
47 };
48 constexpr size_t HugeCallableSize = sizeof(Big) + sizeof(void*) * 4;
49 
50 // An object that looks like an "empty" std::function.
51 template <typename>
52 struct EmptyFunction;
53 template <typename R, typename... Args>
54 struct EmptyFunction<R(Args...)> {
operator ()__anon339fe1ef0111::EmptyFunction55   R operator()(Args... args) const { return fptr(args...); }
operator ==__anon339fe1ef0111::EmptyFunction56   bool operator==(decltype(nullptr)) const { return true; }
57 
58   R(*fptr)
59   (Args...) = nullptr;
60 };
61 
62 struct alignas(4 * alignof(void*)) LargeAlignedCallable {
operator ()__anon339fe1ef0111::LargeAlignedCallable63   void operator()() { calls += 1; }
64 
65   int8_t calls = 0;
66 };
67 
68 // An object whose state we can examine from the outside.
69 struct SlotMachine {
operator ()__anon339fe1ef0111::SlotMachine70   void operator()() { value++; }
operator ()__anon339fe1ef0111::SlotMachine71   int operator()(int a, int b) {
72     value += a * b;
73     return value;
74   }
75 
76   int value = 0;
77 };
78 
79 // A move-only object which increments a counter when uniquely destroyed.
80 class DestructionObserver {
81  public:
DestructionObserver(int * counter)82   DestructionObserver(int* counter) : counter_(counter) {}
DestructionObserver(DestructionObserver && other)83   DestructionObserver(DestructionObserver&& other) : counter_(other.counter_) {
84     other.counter_ = nullptr;
85   }
86   DestructionObserver(const DestructionObserver& other) = delete;
87 
~DestructionObserver()88   ~DestructionObserver() {
89     if (counter_)
90       *counter_ += 1;
91   }
92 
93   DestructionObserver& operator=(const DestructionObserver& other) = delete;
operator =(DestructionObserver && other)94   DestructionObserver& operator=(DestructionObserver&& other) {
95     if (counter_)
96       *counter_ += 1;
97     counter_ = other.counter_;
98     other.counter_ = nullptr;
99     return *this;
100   }
101 
102  private:
103   int* counter_;
104 };
105 
106 // Simple Allocator that only allows 1 object to be allocated/deallocated per call. All template
107 // instantiations share the same resources.
108 template <typename T>
109 class SingleObjectAllocator;
110 
111 // Shared resources for SingleObjectAllocator template instantiations.
112 class SingleObjectAllocatorResources final {
113  private:
114   template <typename T>
115   friend class SingleObjectAllocator;
116 
117   // Tuned to current tests. May need to be changed if test requirements change.
118   static constexpr size_t kObjectSize{HugeCallableSize};
119   static constexpr size_t kObjectAlignment{alignof(LargeAlignedCallable)};
120   static constexpr size_t kMaxNumObjects{2u};
121 
122   struct Obj {
123     alignas(kObjectAlignment) std::byte obj[kObjectSize];
124   };
125 
126   inline static std::array<Obj, kMaxNumObjects> heap_;
127   // Store `bool`s separately instead of in `Obj`, so there doesn't end up being a large amount of
128   // padding from the aligned `obj` arrays in the `Obj` structs.
129   inline static std::array<bool, kMaxNumObjects> in_use_{};
130 };
131 
132 template <typename T>
133 class SingleObjectAllocator final {
134  public:
135   using value_type = T;
136   using pointer = value_type*;
137   using size_type = size_t;
138 
139   struct is_always_equal : public std::true_type {};
140 
141   constexpr SingleObjectAllocator() = default;
142   template <typename U>
SingleObjectAllocator(const SingleObjectAllocator<U> &)143   constexpr SingleObjectAllocator(const SingleObjectAllocator<U>&) {}
144   template <typename U>
SingleObjectAllocator(SingleObjectAllocator<U> &&)145   constexpr SingleObjectAllocator(SingleObjectAllocator<U>&&) {}
146 
allocate(size_type n)147   pointer allocate(size_type n) {
148     if (n != 1u) {
149       return nullptr;
150     }
151     for (size_t index{0u}; index < in_use_.size(); ++index) {
152       if (!in_use_.at(index)) {
153         in_use_.at(index) = true;
154         return reinterpret_cast<pointer>(&heap_.at(index).obj);
155       }
156     }
157     return nullptr;
158   }
159 
deallocate(pointer p,size_type n)160   void deallocate(pointer p, size_type n) {
161     ASSERT_EQ(n, 1u);
162     for (size_t index{0u}; index < heap_.size(); ++index) {
163       if (reinterpret_cast<pointer>(&heap_.at(index).obj) == p) {
164         ASSERT_TRUE(in_use_.at(index));
165         in_use_.at(index) = false;
166         return;
167       }
168     }
169     FAIL();
170   }
171 
max_size() const172   constexpr size_type max_size() const { return 1u; }
173 
174   template <typename U>
operator ==(const SingleObjectAllocator<U> &) const175   constexpr bool operator==(const SingleObjectAllocator<U>&) const {
176     return true;
177   }
178   template <typename U>
operator !=(const SingleObjectAllocator<U> &) const179   constexpr bool operator!=(const SingleObjectAllocator<U>&) const {
180     return false;
181   }
182 
183  private:
184   // Shared resources.
185   static_assert(sizeof(value_type) <= SingleObjectAllocatorResources::kObjectSize);
186   static_assert(alignof(value_type) <= SingleObjectAllocatorResources::kObjectAlignment);
187   inline static auto& heap_ = SingleObjectAllocatorResources::heap_;
188   inline static auto& in_use_ = SingleObjectAllocatorResources::in_use_;
189   static_assert(heap_.size() == in_use_.size());
190 };
191 
192 template <typename ClosureFunction>
closure()193 void closure() {
194   static_assert(fit::is_nullable<ClosureFunction>::value, "");
195 
196   // default initialization
197   ClosureFunction fdefault;
198   EXPECT_FALSE(!!fdefault);
199 
200   // nullptr initialization
201   ClosureFunction fnull(nullptr);
202   EXPECT_FALSE(!!fnull);
203 
204   // null function pointer initialization
205   Closure* fptr = nullptr;
206   ClosureFunction ffunc(fptr);
207   EXPECT_FALSE(!!ffunc);
208 
209   // "empty std::function" initialization
210   EmptyFunction<Closure> empty;
211   ClosureFunction fwrapper(empty);
212   EXPECT_FALSE(!!fwrapper);
213 
214   // inline callable initialization
215   int finline_value = 0;
216   ClosureFunction finline([&finline_value] { finline_value++; });
217   EXPECT_TRUE(!!finline);
218   finline();
219   EXPECT_EQ(1, finline_value);
220   finline();
221   EXPECT_EQ(2, finline_value);
222 
223   // heap callable initialization
224   int fheap_value = 0;
225   ClosureFunction fheap([&fheap_value, big = Big()] { fheap_value++; });
226   EXPECT_TRUE(!!fheap);
227   fheap();
228   EXPECT_EQ(1, fheap_value);
229   fheap();
230   EXPECT_EQ(2, fheap_value);
231 
232   // move initialization of a nullptr
233   ClosureFunction fnull2(std::move(fnull));
234   EXPECT_FALSE(!!fnull2);
235 
236   // move initialization of an inline callable
237   ClosureFunction finline2(std::move(finline));
238   EXPECT_TRUE(!!finline2);
239   EXPECT_FALSE(!!finline);
240   finline2();
241   EXPECT_EQ(3, finline_value);
242   finline2();
243   EXPECT_EQ(4, finline_value);
244 
245   // move initialization of a heap callable
246   ClosureFunction fheap2(std::move(fheap));
247   EXPECT_TRUE(!!fheap2);
248   EXPECT_FALSE(!!fheap);
249   fheap2();
250   EXPECT_EQ(3, fheap_value);
251   fheap2();
252   EXPECT_EQ(4, fheap_value);
253 
254   // inline mutable lambda
255   int fmutinline_value = 0;
256   ClosureFunction fmutinline([&fmutinline_value, x = 1]() mutable {
257     x *= 2;
258     fmutinline_value = x;
259   });
260   EXPECT_TRUE(!!fmutinline);
261   fmutinline();
262   EXPECT_EQ(2, fmutinline_value);
263   fmutinline();
264   EXPECT_EQ(4, fmutinline_value);
265 
266   // heap-allocated mutable lambda
267   int fmutheap_value = 0;
268   ClosureFunction fmutheap([&fmutheap_value, big = Big(), x = 1]() mutable {
269     x *= 2;
270     fmutheap_value = x;
271   });
272   EXPECT_TRUE(!!fmutheap);
273   fmutheap();
274   EXPECT_EQ(2, fmutheap_value);
275   fmutheap();
276   EXPECT_EQ(4, fmutheap_value);
277 
278   // move assignment of non-null
279   ClosureFunction fnew([] {});
280   fnew = std::move(finline2);
281   EXPECT_TRUE(!!fnew);
282   fnew();
283   EXPECT_EQ(5, finline_value);
284   fnew();
285   EXPECT_EQ(6, finline_value);
286 
287   // move assignment of self
288   fnew = std::move(fnew);
289   EXPECT_TRUE(!!fnew);
290   fnew();
291   EXPECT_EQ(7, finline_value);
292 
293   // move assignment of null
294   fnew = std::move(fnull);
295   EXPECT_FALSE(!!fnew);
296 
297   // callable assignment with operator=
298   int fnew_value = 0;
299   fnew = [&fnew_value] { fnew_value++; };
300   EXPECT_TRUE(!!fnew);
301   fnew();
302   EXPECT_EQ(1, fnew_value);
303   fnew();
304   EXPECT_EQ(2, fnew_value);
305 
306   // nullptr assignment
307   fnew = nullptr;
308   EXPECT_FALSE(!!fnew);
309 
310   // swap (currently null)
311   swap(fnew, fheap2);
312   EXPECT_TRUE(!!fnew);
313   EXPECT_FALSE(!!fheap);
314   fnew();
315   EXPECT_EQ(5, fheap_value);
316   fnew();
317   EXPECT_EQ(6, fheap_value);
318 
319   // swap with self
320   swap(fnew, fnew);
321   EXPECT_TRUE(!!fnew);
322   fnew();
323   EXPECT_EQ(7, fheap_value);
324   fnew();
325   EXPECT_EQ(8, fheap_value);
326 
327   // swap with non-null
328   swap(fnew, fmutinline);
329   EXPECT_TRUE(!!fmutinline);
330   EXPECT_TRUE(!!fnew);
331   fmutinline();
332   EXPECT_EQ(9, fheap_value);
333   fmutinline();
334   EXPECT_EQ(10, fheap_value);
335   fnew();
336   EXPECT_EQ(8, fmutinline_value);
337   fnew();
338   EXPECT_EQ(16, fmutinline_value);
339 
340   // nullptr comparison operators
341   EXPECT_TRUE(fnull == nullptr);
342   EXPECT_FALSE(fnull != nullptr);
343   EXPECT_TRUE(nullptr == fnull);
344   EXPECT_FALSE(nullptr != fnull);
345   EXPECT_FALSE(fnew == nullptr);
346   EXPECT_TRUE(fnew != nullptr);
347   EXPECT_FALSE(nullptr == fnew);
348   EXPECT_TRUE(nullptr != fnew);
349 
350   // null function pointer assignment
351   fnew = fptr;
352   EXPECT_FALSE(!!fnew);
353 
354   // "empty std::function" assignment
355   fmutinline = empty;
356   EXPECT_FALSE(!!fmutinline);
357 
358   // target access
359   ClosureFunction fslot;
360   EXPECT_NULL(fslot.template target<decltype(nullptr)>());
361   fslot = SlotMachine{42};
362   fslot();
363   SlotMachine* fslottarget = fslot.template target<SlotMachine>();
364   EXPECT_EQ(43, fslottarget->value);
365   const SlotMachine* fslottargetconst =
366       const_cast<const ClosureFunction&>(fslot).template target<SlotMachine>();
367   EXPECT_EQ(fslottarget, fslottargetconst);
368   fslot = nullptr;
369   EXPECT_NULL(fslot.template target<decltype(nullptr)>());
370 }
371 
372 template <typename BinaryOpFunction>
binary_op()373 void binary_op() {
374   static_assert(fit::is_nullable<BinaryOpFunction>::value, "");
375 
376   // default initialization
377   BinaryOpFunction fdefault;
378   EXPECT_FALSE(!!fdefault);
379 
380   // nullptr initialization
381   BinaryOpFunction fnull(nullptr);
382   EXPECT_FALSE(!!fnull);
383 
384   // null function pointer initialization
385   BinaryOp* fptr = nullptr;
386   BinaryOpFunction ffunc(fptr);
387   EXPECT_FALSE(!!ffunc);
388 
389   // "empty std::function" initialization
390   EmptyFunction<BinaryOp> empty;
391   BinaryOpFunction fwrapper(empty);
392   EXPECT_FALSE(!!fwrapper);
393 
394   // inline callable initialization
395   int finline_value = 0;
396   BinaryOpFunction finline([&finline_value](int a, int b) {
397     finline_value++;
398     return a + b;
399   });
400   EXPECT_TRUE(!!finline);
401   EXPECT_EQ(10, finline(3, 7));
402   EXPECT_EQ(1, finline_value);
403   EXPECT_EQ(10, finline(3, 7));
404   EXPECT_EQ(2, finline_value);
405 
406   // heap callable initialization
407   int fheap_value = 0;
408   BinaryOpFunction fheap([&fheap_value, big = Big()](int a, int b) {
409     fheap_value++;
410     return a + b;
411   });
412   EXPECT_TRUE(!!fheap);
413   EXPECT_EQ(10, fheap(3, 7));
414   EXPECT_EQ(1, fheap_value);
415   EXPECT_EQ(10, fheap(3, 7));
416   EXPECT_EQ(2, fheap_value);
417 
418   // move initialization of a nullptr
419   BinaryOpFunction fnull2(std::move(fnull));
420   EXPECT_FALSE(!!fnull2);
421 
422   // move initialization of an inline callable
423   BinaryOpFunction finline2(std::move(finline));
424   EXPECT_TRUE(!!finline2);
425   EXPECT_FALSE(!!finline);
426   EXPECT_EQ(10, finline2(3, 7));
427   EXPECT_EQ(3, finline_value);
428   EXPECT_EQ(10, finline2(3, 7));
429   EXPECT_EQ(4, finline_value);
430 
431   // move initialization of a heap callable
432   BinaryOpFunction fheap2(std::move(fheap));
433   EXPECT_TRUE(!!fheap2);
434   EXPECT_FALSE(!!fheap);
435   EXPECT_EQ(10, fheap2(3, 7));
436   EXPECT_EQ(3, fheap_value);
437   EXPECT_EQ(10, fheap2(3, 7));
438   EXPECT_EQ(4, fheap_value);
439 
440   // inline mutable lambda
441   int fmutinline_value = 0;
442   BinaryOpFunction fmutinline([&fmutinline_value, x = 1](int a, int b) mutable {
443     x *= 2;
444     fmutinline_value = x;
445     return a + b;
446   });
447   EXPECT_TRUE(!!fmutinline);
448   EXPECT_EQ(10, fmutinline(3, 7));
449   EXPECT_EQ(2, fmutinline_value);
450   EXPECT_EQ(10, fmutinline(3, 7));
451   EXPECT_EQ(4, fmutinline_value);
452 
453   // heap-allocated mutable lambda
454   int fmutheap_value = 0;
455   BinaryOpFunction fmutheap([&fmutheap_value, big = Big(), x = 1](int a, int b) mutable {
456     x *= 2;
457     fmutheap_value = x;
458     return a + b;
459   });
460   EXPECT_TRUE(!!fmutheap);
461   EXPECT_EQ(10, fmutheap(3, 7));
462   EXPECT_EQ(2, fmutheap_value);
463   EXPECT_EQ(10, fmutheap(3, 7));
464   EXPECT_EQ(4, fmutheap_value);
465 
466   // move assignment of non-null
467   BinaryOpFunction fnew([](int a, int b) { return 0; });
468   fnew = std::move(finline2);
469   EXPECT_TRUE(!!fnew);
470   EXPECT_EQ(10, fnew(3, 7));
471   EXPECT_EQ(5, finline_value);
472   EXPECT_EQ(10, fnew(3, 7));
473   EXPECT_EQ(6, finline_value);
474 
475   // self-assignment of non-null
476   fnew = std::move(fnew);
477   EXPECT_TRUE(!!fnew);
478   EXPECT_EQ(10, fnew(3, 7));
479   EXPECT_EQ(7, finline_value);
480 
481   // move assignment of null
482   fnew = std::move(fnull);
483   EXPECT_FALSE(!!fnew);
484 
485   // self-assignment of non-null
486   fnew = std::move(fnew);
487   EXPECT_FALSE(!!fnew);
488 
489   // callable assignment with operator=
490   int fnew_value = 0;
491   fnew = [&fnew_value](int a, int b) {
492     fnew_value++;
493     return a + b;
494   };
495   EXPECT_TRUE(!!fnew);
496   EXPECT_EQ(10, fnew(3, 7));
497   EXPECT_EQ(1, fnew_value);
498   EXPECT_EQ(10, fnew(3, 7));
499   EXPECT_EQ(2, fnew_value);
500 
501   // nullptr assignment
502   fnew = nullptr;
503   EXPECT_FALSE(!!fnew);
504 
505   // swap (currently null)
506   swap(fnew, fheap2);
507   EXPECT_TRUE(!!fnew);
508   EXPECT_FALSE(!!fheap);
509   EXPECT_EQ(10, fnew(3, 7));
510   EXPECT_EQ(5, fheap_value);
511   EXPECT_EQ(10, fnew(3, 7));
512   EXPECT_EQ(6, fheap_value);
513 
514   // swap with self
515   swap(fnew, fnew);
516   EXPECT_TRUE(!!fnew);
517   EXPECT_EQ(10, fnew(3, 7));
518   EXPECT_EQ(7, fheap_value);
519   EXPECT_EQ(10, fnew(3, 7));
520   EXPECT_EQ(8, fheap_value);
521 
522   // swap with non-null
523   swap(fnew, fmutinline);
524   EXPECT_TRUE(!!fmutinline);
525   EXPECT_TRUE(!!fnew);
526   EXPECT_EQ(10, fmutinline(3, 7));
527   EXPECT_EQ(9, fheap_value);
528   EXPECT_EQ(10, fmutinline(3, 7));
529   EXPECT_EQ(10, fheap_value);
530   EXPECT_EQ(10, fnew(3, 7));
531   EXPECT_EQ(8, fmutinline_value);
532   EXPECT_EQ(10, fnew(3, 7));
533   EXPECT_EQ(16, fmutinline_value);
534 
535   // nullptr comparison operators
536   EXPECT_TRUE(fnull == nullptr);
537   EXPECT_FALSE(fnull != nullptr);
538   EXPECT_TRUE(nullptr == fnull);
539   EXPECT_FALSE(nullptr != fnull);
540   EXPECT_FALSE(fnew == nullptr);
541   EXPECT_TRUE(fnew != nullptr);
542   EXPECT_FALSE(nullptr == fnew);
543   EXPECT_TRUE(nullptr != fnew);
544 
545   // null function pointer assignment
546   fnew = fptr;
547   EXPECT_FALSE(!!fnew);
548 
549   // "empty std::function" assignment
550   fmutinline = empty;
551   EXPECT_FALSE(!!fmutinline);
552 
553   // target access
554   BinaryOpFunction fslot;
555   EXPECT_NULL(fslot.template target<decltype(nullptr)>());
556   fslot = SlotMachine{42};
557   EXPECT_EQ(54, fslot(3, 4));
558   SlotMachine* fslottarget = fslot.template target<SlotMachine>();
559   EXPECT_EQ(54, fslottarget->value);
560   const SlotMachine* fslottargetconst =
561       const_cast<const BinaryOpFunction&>(fslot).template target<SlotMachine>();
562   EXPECT_EQ(fslottarget, fslottargetconst);
563   fslot = nullptr;
564   EXPECT_NULL(fslot.template target<decltype(nullptr)>());
565 }
566 
TEST(FunctionTests,sized_function_size_bounds)567 TEST(FunctionTests, sized_function_size_bounds) {
568   auto empty = [] {};
569   fit::function<Closure, sizeof(empty)> fempty(std::move(empty));
570   static_assert(sizeof(fempty) >= sizeof(empty), "size bounds");
571 
572   auto small = [x = 1, y = 2] {
573     (void)x;  // suppress unused lambda capture warning
574     (void)y;
575   };
576   fit::function<Closure, sizeof(small)> fsmall(std::move(small));
577   static_assert(sizeof(fsmall) >= sizeof(small), "size bounds");
578   fsmall = [] {};
579 
580   auto big = [big = Big(), x = 1] { (void)x; };
581   fit::function<Closure, sizeof(big)> fbig(std::move(big));
582   static_assert(sizeof(fbig) >= sizeof(big), "size bounds");
583   fbig = [x = 1, y = 2] {
584     (void)x;
585     (void)y;
586   };
587   fbig = [] {};
588 
589   // These statements do compile though the lambda will be copied to the heap
590   // when they exceed the inline size.
591   fempty = [x = 1, y = 2] {
592     (void)x;
593     (void)y;
594   };
595   fsmall = [big = Big(), x = 1] { (void)x; };
596   fbig = [big = Big(), x = 1, y = 2] {
597     (void)x;
598     (void)y;
599   };
600 }
601 
TEST(FunctionTests,inline_function_size_bounds)602 TEST(FunctionTests, inline_function_size_bounds) {
603   auto empty = [] {};
604   fit::inline_function<Closure, sizeof(empty)> fempty(std::move(empty));
605   static_assert(sizeof(fempty) >= sizeof(empty), "size bounds");
606 
607   auto small = [x = 1, y = 2] {
608     (void)x;  // suppress unused lambda capture warning
609     (void)y;
610   };
611   fit::inline_function<Closure, sizeof(small)> fsmall(std::move(small));
612   static_assert(sizeof(fsmall) >= sizeof(small), "size bounds");
613   fsmall = [] {};
614 
615   auto big = [big = Big(), x = 1] { (void)x; };
616   fit::inline_function<Closure, sizeof(big)> fbig(std::move(big));
617   static_assert(sizeof(fbig) >= sizeof(big), "size bounds");
618   fbig = [x = 1, y = 2] {
619     (void)x;
620     (void)y;
621   };
622   fbig = [] {};
623 
624 // These statements do not compile because the lambdas are too big to fit.
625 #if 0
626     fempty = [ x = 1, y = 2 ] {
627         (void)x;
628         (void)y;
629     };
630     fsmall = [ big = Big(), x = 1 ] { (void)x; };
631     fbig = [ big = Big(), x = 1, y = 2 ] {
632         (void)x;
633         (void)y;
634     };
635 #endif
636 }
637 
TEST(FunctionTests,inline_function_alignment_check)638 TEST(FunctionTests, inline_function_alignment_check) {
639 // These statements do not compile because the alignment is too large.
640 #if 0
641     auto big = [big = BigAlignment()] { };
642     fit::inline_function<Closure, sizeof(big)> fbig(std::move(big));
643 #endif
644 }
645 
TEST(FunctionTests,move_only_argument_and_result)646 TEST(FunctionTests, move_only_argument_and_result) {
647   std::unique_ptr<int> arg(new int());
648   fit::function<MoveOp> f([](std::unique_ptr<int> value) {
649     *value += 1;
650     return value;
651   });
652   arg = f(std::move(arg));
653   EXPECT_EQ(1, *arg);
654   arg = f(std::move(arg));
655   EXPECT_EQ(2, *arg);
656 }
657 
implicit_construction_helper(fit::closure closure)658 void implicit_construction_helper(fit::closure closure) {}
659 
TEST(FunctionTests,implicit_construction)660 TEST(FunctionTests, implicit_construction) {
661   // ensure we can implicitly construct from nullptr
662   implicit_construction_helper(nullptr);
663 
664   // ensure we can implicitly construct from a lambda
665   implicit_construction_helper([] {});
666 }
667 
arg_count(fit::closure)668 int arg_count(fit::closure) { return 0; }
arg_count(fit::function<void (int)>)669 int arg_count(fit::function<void(int)>) { return 1; }
670 
TEST(FunctionTests,overload_resolution)671 TEST(FunctionTests, overload_resolution) {
672   EXPECT_EQ(0, arg_count([] {}));
673   EXPECT_EQ(1, arg_count([](int) {}));
674 }
675 
TEST(FunctionTests,sharing)676 TEST(FunctionTests, sharing) {
677   fit::function<Closure> fnull;
678   fit::function<Closure> fnullshare1 = fnull.share();
679   fit::function<Closure> fnullshare2 = fnull.share();
680   fit::function<Closure> fnullshare3 = fnullshare1.share();
681   EXPECT_FALSE(!!fnull);
682   EXPECT_FALSE(!!fnullshare1);
683   EXPECT_FALSE(!!fnullshare2);
684   EXPECT_FALSE(!!fnullshare3);
685 
686   int finlinevalue = 1;
687   int finlinedestroy = 0;
688   fit::function<Closure> finline = [&finlinevalue, d = DestructionObserver(&finlinedestroy)] {
689     finlinevalue++;
690   };
691   fit::function<Closure> finlineshare1 = finline.share();
692   fit::function<Closure> finlineshare2 = finline.share();
693   fit::function<Closure> finlineshare3 = finlineshare1.share();
694   EXPECT_TRUE(!!finline);
695   EXPECT_TRUE(!!finlineshare1);
696   EXPECT_TRUE(!!finlineshare2);
697   EXPECT_TRUE(!!finlineshare3);
698   finline();
699   EXPECT_EQ(2, finlinevalue);
700   finlineshare1();
701   EXPECT_EQ(3, finlinevalue);
702   finlineshare2();
703   EXPECT_EQ(4, finlinevalue);
704   finlineshare3();
705   EXPECT_EQ(5, finlinevalue);
706   finlineshare2();
707   EXPECT_EQ(6, finlinevalue);
708   finline();
709   EXPECT_EQ(7, finlinevalue);
710   EXPECT_EQ(0, finlinedestroy);
711   finline = nullptr;
712   EXPECT_EQ(0, finlinedestroy);
713   finlineshare3 = nullptr;
714   EXPECT_EQ(0, finlinedestroy);
715   finlineshare2 = nullptr;
716   EXPECT_EQ(0, finlinedestroy);
717   finlineshare1 = nullptr;
718   EXPECT_EQ(1, finlinedestroy);
719 
720   int fheapvalue = 1;
721   int fheapdestroy = 0;
722   fit::function<Closure> fheap = [&fheapvalue, big = Big(),
723                                   d = DestructionObserver(&fheapdestroy)] { fheapvalue++; };
724   fit::function<Closure> fheapshare1 = fheap.share();
725   fit::function<Closure> fheapshare2 = fheap.share();
726   fit::function<Closure> fheapshare3 = fheapshare1.share();
727   EXPECT_TRUE(!!fheap);
728   EXPECT_TRUE(!!fheapshare1);
729   EXPECT_TRUE(!!fheapshare2);
730   EXPECT_TRUE(!!fheapshare3);
731   fheap();
732   EXPECT_EQ(2, fheapvalue);
733   fheapshare1();
734   EXPECT_EQ(3, fheapvalue);
735   fheapshare2();
736   EXPECT_EQ(4, fheapvalue);
737   fheapshare3();
738   EXPECT_EQ(5, fheapvalue);
739   fheapshare2();
740   EXPECT_EQ(6, fheapvalue);
741   fheap();
742   EXPECT_EQ(7, fheapvalue);
743   EXPECT_EQ(0, fheapdestroy);
744   fheap = nullptr;
745   EXPECT_EQ(0, fheapdestroy);
746   fheapshare3 = nullptr;
747   EXPECT_EQ(0, fheapdestroy);
748   fheapshare2 = nullptr;
749   EXPECT_EQ(0, fheapdestroy);
750   fheapshare1 = nullptr;
751   EXPECT_EQ(1, fheapdestroy);
752 
753   // target access now available after share()
754   using ClosureFunction = fit::function<Closure, HugeCallableSize>;
755   ClosureFunction fslot = SlotMachine{42};
756   fslot();
757   SlotMachine* fslottarget = fslot.template target<SlotMachine>();
758   EXPECT_EQ(43, fslottarget->value);
759 
760   auto shared_fslot = fslot.share();
761   shared_fslot();
762   fslottarget = shared_fslot.template target<SlotMachine>();
763   EXPECT_EQ(44, fslottarget->value);
764   fslot();
765   EXPECT_EQ(45, fslottarget->value);
766   fslot = nullptr;
767   EXPECT_NULL(fslot.template target<decltype(nullptr)>());
768   shared_fslot();
769   EXPECT_EQ(46, fslottarget->value);
770   shared_fslot = nullptr;
771   EXPECT_NULL(shared_fslot.template target<decltype(nullptr)>());
772 
773 // These statements do not compile because inline functions cannot be shared
774 #if 0
775     fit::inline_function<Closure> fbad;
776     fbad.share();
777 #endif
778 }
779 
TEST(FunctionTests,sharing_with_custom_allocator)780 TEST(FunctionTests, sharing_with_custom_allocator) {
781   int fheapvalue = 1;
782   int fheapdestroy = 0;
783   fit::function<Closure, fit::default_inline_target_size, SingleObjectAllocator<std::byte>> fheap =
784       [&fheapvalue, big = Big(), d = DestructionObserver(&fheapdestroy)] { fheapvalue++; };
785   fit::function<Closure, fit::default_inline_target_size, SingleObjectAllocator<std::byte>>
786       fheapshare1 = fheap.share();
787   fit::function<Closure, fit::default_inline_target_size, SingleObjectAllocator<std::byte>>
788       fheapshare2 = fheap.share();
789   fit::function<Closure, fit::default_inline_target_size, SingleObjectAllocator<std::byte>>
790       fheapshare3 = fheapshare1.share();
791   EXPECT_TRUE(!!fheap);
792   EXPECT_TRUE(!!fheapshare1);
793   EXPECT_TRUE(!!fheapshare2);
794   EXPECT_TRUE(!!fheapshare3);
795   fheap();
796   EXPECT_EQ(2, fheapvalue);
797   fheapshare1();
798   EXPECT_EQ(3, fheapvalue);
799   fheapshare2();
800   EXPECT_EQ(4, fheapvalue);
801   fheapshare3();
802   EXPECT_EQ(5, fheapvalue);
803   fheapshare2();
804   EXPECT_EQ(6, fheapvalue);
805   fheap();
806   EXPECT_EQ(7, fheapvalue);
807   EXPECT_EQ(0, fheapdestroy);
808   fheap = nullptr;
809   EXPECT_EQ(0, fheapdestroy);
810   fheapshare3 = nullptr;
811   EXPECT_EQ(0, fheapdestroy);
812   fheapshare2 = nullptr;
813   EXPECT_EQ(0, fheapdestroy);
814   fheapshare1 = nullptr;
815   EXPECT_EQ(1, fheapdestroy);
816 }
817 
818 struct Obj {
Call__anon339fe1ef0111::Obj819   void Call() { calls++; }
820 
AddOne__anon339fe1ef0111::Obj821   int AddOne(int x) {
822     calls++;
823     return x + 1;
824   }
825 
Sum__anon339fe1ef0111::Obj826   int Sum(int a, int b, int c) {
827     calls++;
828     return a + b + c;
829   }
830 
AddAndReturn__anon339fe1ef0111::Obj831   std::unique_ptr<int> AddAndReturn(std::unique_ptr<int> value) {
832     (*value)++;
833     return value;
834   }
835 
836   uint32_t calls = 0;
837 };
838 
TEST(FunctionTests,deprecated_bind_member)839 TEST(FunctionTests, deprecated_bind_member) {
840   Obj obj;
841   auto move_only_value = std::make_unique<int>(4);
842 
843   static_assert(sizeof(fit::bind_member(&obj, &Obj::AddOne)) == 3 * sizeof(void*));
844   fit::bind_member(&obj, &Obj::Call)();
845   EXPECT_EQ(23, fit::bind_member(&obj, &Obj::AddOne)(22));
846   EXPECT_EQ(6, fit::bind_member(&obj, &Obj::Sum)(1, 2, 3));
847   move_only_value = fit::bind_member(&obj, &Obj::AddAndReturn)(std::move(move_only_value));
848   EXPECT_EQ(5, *move_only_value);
849   EXPECT_EQ(3, obj.calls);
850 }
851 
TEST(FunctionTests,bind_member)852 TEST(FunctionTests, bind_member) {
853   Obj obj;
854   auto move_only_value = std::make_unique<int>(4);
855 
856   static_assert(sizeof(fit::bind_member<&Obj::AddOne>(&obj)) == sizeof(void*));
857   fit::bind_member<&Obj::Call> (&obj)();
858   EXPECT_EQ(23, fit::bind_member<&Obj::AddOne>(&obj)(22));
859   EXPECT_EQ(6, fit::bind_member<&Obj::Sum>(&obj)(1, 2, 3));
860   move_only_value = fit::bind_member<&Obj::AddAndReturn>(&obj)(std::move(move_only_value));
861   fit::function<int(int, int, int)> f(fit::bind_member<&Obj::Sum>(&obj));
862   EXPECT_EQ(6, f(1, 2, 3));
863   EXPECT_EQ(5, *move_only_value);
864   EXPECT_EQ(4, obj.calls);
865 }
866 
TEST(FunctionTests,callback_once)867 TEST(FunctionTests, callback_once) {
868   fit::callback<Closure> cbnull;
869   fit::callback<Closure> cbnullshare1 = cbnull.share();
870   fit::callback<Closure> cbnullshare2 = cbnull.share();
871   fit::callback<Closure> cbnullshare3 = cbnullshare1.share();
872   EXPECT_FALSE(!!cbnull);
873   EXPECT_FALSE(!!cbnullshare1);
874   EXPECT_FALSE(!!cbnullshare2);
875   EXPECT_FALSE(!!cbnullshare3);
876 
877   int cbinlinevalue = 1;
878   int cbinlinedestroy = 0;
879   fit::callback<Closure> cbinline = [&cbinlinevalue, d = DestructionObserver(&cbinlinedestroy)] {
880     cbinlinevalue++;
881   };
882   EXPECT_TRUE(!!cbinline);
883   EXPECT_FALSE(cbinline == nullptr);
884   EXPECT_EQ(1, cbinlinevalue);
885   EXPECT_EQ(0, cbinlinedestroy);
886   cbinline();  // releases resources even if never shared
887   EXPECT_FALSE(!!cbinline);
888   EXPECT_TRUE(cbinline == nullptr);
889   EXPECT_EQ(2, cbinlinevalue);
890   EXPECT_EQ(1, cbinlinedestroy);
891 
892   cbinlinevalue = 1;
893   cbinlinedestroy = 0;
894   cbinline = [&cbinlinevalue, d = DestructionObserver(&cbinlinedestroy)] { cbinlinevalue++; };
895   fit::callback<Closure> cbinlineshare1 = cbinline.share();
896   fit::callback<Closure> cbinlineshare2 = cbinline.share();
897   fit::callback<Closure> cbinlineshare3 = cbinlineshare1.share();
898   EXPECT_TRUE(!!cbinline);
899   EXPECT_TRUE(!!cbinlineshare1);
900   EXPECT_TRUE(!!cbinlineshare2);
901   EXPECT_TRUE(!!cbinlineshare3);
902   EXPECT_EQ(1, cbinlinevalue);
903   EXPECT_EQ(0, cbinlinedestroy);
904   cbinline();
905   EXPECT_EQ(2, cbinlinevalue);
906   EXPECT_EQ(1, cbinlinedestroy);
907   EXPECT_FALSE(!!cbinline);
908   EXPECT_TRUE(cbinline == nullptr);
909   // cbinline(); // should abort
910   EXPECT_FALSE(!!cbinlineshare1);
911   EXPECT_TRUE(cbinlineshare1 == nullptr);
912   // cbinlineshare1(); // should abort
913   EXPECT_FALSE(!!cbinlineshare2);
914   // cbinlineshare2(); // should abort
915   EXPECT_FALSE(!!cbinlineshare3);
916   // cbinlineshare3(); // should abort
917   EXPECT_EQ(1, cbinlinedestroy);
918   cbinlineshare3 = nullptr;
919   EXPECT_EQ(1, cbinlinedestroy);
920   cbinline = nullptr;
921   EXPECT_EQ(1, cbinlinedestroy);
922 
923   int cbheapvalue = 1;
924   int cbheapdestroy = 0;
925   fit::callback<Closure> cbheap = [&cbheapvalue, big = Big(),
926                                    d = DestructionObserver(&cbheapdestroy)] { cbheapvalue++; };
927   EXPECT_TRUE(!!cbheap);
928   EXPECT_FALSE(cbheap == nullptr);
929   EXPECT_EQ(1, cbheapvalue);
930   EXPECT_EQ(0, cbheapdestroy);
931   cbheap();  // releases resources even if never shared
932   EXPECT_FALSE(!!cbheap);
933   EXPECT_TRUE(cbheap == nullptr);
934   EXPECT_EQ(2, cbheapvalue);
935   EXPECT_EQ(1, cbheapdestroy);
936 
937   cbheapvalue = 1;
938   cbheapdestroy = 0;
939   cbheap = [&cbheapvalue, big = Big(), d = DestructionObserver(&cbheapdestroy)] { cbheapvalue++; };
940   fit::callback<Closure> cbheapshare1 = cbheap.share();
941   fit::callback<Closure> cbheapshare2 = cbheap.share();
942   fit::callback<Closure> cbheapshare3 = cbheapshare1.share();
943   EXPECT_TRUE(!!cbheap);
944   EXPECT_TRUE(!!cbheapshare1);
945   EXPECT_TRUE(!!cbheapshare2);
946   EXPECT_TRUE(!!cbheapshare3);
947   EXPECT_EQ(1, cbheapvalue);
948   EXPECT_EQ(0, cbheapdestroy);
949   cbheap();
950   EXPECT_EQ(2, cbheapvalue);
951   EXPECT_EQ(1, cbheapdestroy);
952   EXPECT_FALSE(!!cbheap);
953   EXPECT_TRUE(cbheap == nullptr);
954   // cbheap(); // should abort
955   EXPECT_FALSE(!!cbheapshare1);
956   EXPECT_TRUE(cbheapshare1 == nullptr);
957   // cbheapshare1(); // should abort
958   EXPECT_FALSE(!!cbheapshare2);
959   // cbheapshare2(); // should abort
960   EXPECT_FALSE(!!cbheapshare3);
961   // cbheapshare3(); // should abort
962   EXPECT_EQ(1, cbheapdestroy);
963   cbheapshare3 = nullptr;
964   EXPECT_EQ(1, cbheapdestroy);
965   cbheap = nullptr;
966   EXPECT_EQ(1, cbheapdestroy);
967 
968   // Verify new design, splitting out fit::callback, still supports
969   // assignment of move-only "Callables" (that is, lambdas made move-only
970   // because they capture a move-only object, like a fit::function, for
971   // example!)
972   fit::function<void()> fn_to_wrap = []() {};
973   fit::function<void()> fn_from_lambda;
974   fn_from_lambda = [fn = fn_to_wrap.share()]() mutable { fn(); };
975 
976   // Same test for fit::callback
977   fit::callback<void()> cb_to_wrap = []() {};
978   fit::callback<void()> cb_from_lambda;
979   cb_from_lambda = [cb = std::move(cb_to_wrap)]() mutable { cb(); };
980 
981   // |fit::function| objects can be constructed from or assigned from
982   // a |fit::callback|, if the result and arguments are compatible.
983   fit::function<Closure> fn = []() {};
984   fit::callback<Closure> cb = []() {};
985   fit::callback<Closure> cb_assign;
986   cb_assign = std::move(fn);
987   fit::callback<Closure> cb_construct = std::move(fn);
988   fit::callback<Closure> cb_share = fn.share();
989 
990   static_assert(!std::is_convertible<fit::function<void()>*, fit::callback<void()>*>::value, "");
991   static_assert(!std::is_constructible<fit::function<void()>, fit::callback<void()>>::value, "");
992   static_assert(!std::is_assignable<fit::function<void()>, fit::callback<void()>>::value, "");
993   static_assert(!std::is_constructible<fit::function<void()>, decltype(cb.share())>::value, "");
994 #if 0
995     // These statements do not compile because inline callbacks cannot be shared
996     fit::inline_callback<Closure> cbbad;
997     cbbad.share();
998 
999     {
1000         // Attempts to copy, move, or share a callback into a fit::function<>
1001         // should not compile. This is verified by static_assert above, and
1002         // was verified interactively using the compiler.
1003         fit::callback<Closure> cb = []() {};
1004         fit::function<Closure> fn = []() {};
1005         fit::function<Closure> fn_assign;
1006         fn_assign = cb;                                       // BAD
1007         fn_assign = std::move(cb);                            // BAD
1008         fit::function<Closure> fn_construct = cb;             // BAD
1009         fit::function<Closure> fn_construct2 = std::move(cb); // BAD
1010         fit::function<Closure> fn_share = cb.share();         // BAD
1011     }
1012 
1013 #endif
1014 }
1015 
TEST(FunctionTests,callback_with_custom_allocator)1016 TEST(FunctionTests, callback_with_custom_allocator) {
1017   int cbheapvalue = 1;
1018   int cbheapdestroy = 0;
1019   fit::callback<Closure, fit::default_inline_target_size, SingleObjectAllocator<std::byte>> cbheap =
1020       [&cbheapvalue, big = Big(), d = DestructionObserver(&cbheapdestroy)] { cbheapvalue++; };
1021 
1022   EXPECT_TRUE(!!cbheap);
1023   EXPECT_FALSE(cbheap == nullptr);
1024   EXPECT_EQ(1, cbheapvalue);
1025   EXPECT_EQ(0, cbheapdestroy);
1026   cbheap();
1027   EXPECT_FALSE(!!cbheap);
1028   EXPECT_TRUE(cbheap == nullptr);
1029   EXPECT_EQ(2, cbheapvalue);
1030   EXPECT_EQ(1, cbheapdestroy);
1031 }
1032 
1033 PW_CONSTINIT const fit::function<void()> kDefaultConstructed;
1034 PW_CONSTINIT const fit::function<void()> kNullptrConstructed(nullptr);
1035 
TEST(FunctionTests,null_constructors_are_constexpr)1036 TEST(FunctionTests, null_constructors_are_constexpr) {
1037   EXPECT_EQ(kDefaultConstructed, nullptr);
1038   EXPECT_EQ(kNullptrConstructed, nullptr);
1039 }
1040 
TEST(FunctionTests,function_with_callable_aligned_larger_than_inline_size)1041 TEST(FunctionTests, function_with_callable_aligned_larger_than_inline_size) {
1042   static_assert(sizeof(LargeAlignedCallable) > sizeof(void*), "Should not fit inline in function.");
1043 
1044   fit::function<void(), sizeof(void*)> function = LargeAlignedCallable();
1045 
1046   static_assert(alignof(LargeAlignedCallable) > alignof(decltype(function)));
1047 
1048   // Verify that the allocated target is aligned correctly.
1049   LargeAlignedCallable* callable_ptr = function.target<LargeAlignedCallable>();
1050   EXPECT_EQ(cpp20::bit_cast<uintptr_t>(callable_ptr) % alignof(LargeAlignedCallable), 0u);
1051 
1052   function();
1053   EXPECT_EQ(callable_ptr->calls, 1);
1054 }
1055 
TEST(FunctionTests,function_with_callable_aligned_larger_than_inline_size_with_custom_allocator)1056 TEST(FunctionTests, function_with_callable_aligned_larger_than_inline_size_with_custom_allocator) {
1057   static_assert(sizeof(LargeAlignedCallable) > sizeof(void*), "Should not fit inline in function.");
1058 
1059   fit::function<void(), sizeof(void*), SingleObjectAllocator<std::byte>> function =
1060       LargeAlignedCallable();
1061 
1062   static_assert(alignof(LargeAlignedCallable) > alignof(decltype(function)));
1063 
1064   // Verify that the allocated target is aligned correctly.
1065   LargeAlignedCallable* callable_ptr = function.target<LargeAlignedCallable>();
1066   EXPECT_EQ(cpp20::bit_cast<uintptr_t>(callable_ptr) % alignof(LargeAlignedCallable), 0u);
1067 
1068   function();
1069   EXPECT_EQ(callable_ptr->calls, 1);
1070 }
1071 
1072 // Test that function inline sizes round up to the nearest word.
1073 template <size_t bytes>
1074 using Function = fit::function<void(), bytes>;  // Use an alias for brevity
1075 
1076 static_assert(std::is_same<Function<0>, Function<sizeof(void*)>>::value, "");
1077 static_assert(std::is_same<Function<1>, Function<sizeof(void*)>>::value, "");
1078 static_assert(std::is_same<Function<sizeof(void*) - 1>, Function<sizeof(void*)>>::value, "");
1079 static_assert(std::is_same<Function<sizeof(void*)>, Function<sizeof(void*)>>::value, "");
1080 static_assert(std::is_same<Function<sizeof(void*) + 1>, Function<2 * sizeof(void*)>>::value, "");
1081 static_assert(std::is_same<Function<2 * sizeof(void*)>, Function<2 * sizeof(void*)>>::value, "");
1082 
1083 // Also test the inline_function, callback, and inline_callback aliases.
1084 static_assert(
1085     std::is_same_v<fit::inline_function<void(), 0>, fit::inline_function<void(), sizeof(void*)>>,
1086     "");
1087 static_assert(
1088     std::is_same_v<fit::inline_function<void(), 1>, fit::inline_function<void(), sizeof(void*)>>,
1089     "");
1090 static_assert(std::is_same_v<fit::callback<void(), 0>, fit::callback<void(), sizeof(void*)>>, "");
1091 static_assert(std::is_same_v<fit::callback<void(), 1>, fit::callback<void(), sizeof(void*)>>, "");
1092 static_assert(
1093     std::is_same_v<fit::inline_callback<void(), 0>, fit::inline_callback<void(), sizeof(void*)>>,
1094     "");
1095 static_assert(
1096     std::is_same_v<fit::inline_callback<void(), 1>, fit::inline_callback<void(), sizeof(void*)>>,
1097     "");
1098 
TEST(FunctionTests,rounding_function)1099 TEST(FunctionTests, rounding_function) {
1100   EXPECT_EQ(5, fit::internal::RoundUpToMultiple(0, 5));
1101   EXPECT_EQ(5, fit::internal::RoundUpToMultiple(1, 5));
1102   EXPECT_EQ(5, fit::internal::RoundUpToMultiple(4, 5));
1103   EXPECT_EQ(5, fit::internal::RoundUpToMultiple(5, 5));
1104   EXPECT_EQ(10, fit::internal::RoundUpToMultiple(6, 5));
1105   EXPECT_EQ(10, fit::internal::RoundUpToMultiple(9, 5));
1106   EXPECT_EQ(10, fit::internal::RoundUpToMultiple(10, 5));
1107 }
1108 
1109 // Test that the alignment of function and callback is always the minimum of alignof(max_align_t)
1110 // and largest possible alignment for the specified inline target size.
ExpectedAlignment(size_t alignment_32,size_t alignment_64)1111 constexpr size_t ExpectedAlignment(size_t alignment_32, size_t alignment_64) {
1112   if (sizeof(void*) == 4) {
1113     return std::min(alignment_32, alignof(max_align_t));
1114   }
1115   if (sizeof(void*) == 8) {
1116     return std::min(alignment_64, alignof(max_align_t));
1117   }
1118   return 0;  // Word sizes other than 32/64 are not supported, will need to update test.
1119 }
1120 
1121 static_assert(alignof(fit::function<void(), 0>) == ExpectedAlignment(4, 8), "");
1122 static_assert(alignof(fit::function<void(), 1>) == ExpectedAlignment(4, 8), "");
1123 static_assert(alignof(fit::function<int(), 4>) == ExpectedAlignment(4, 8), "");
1124 static_assert(alignof(fit::function<bool(), 8>) == ExpectedAlignment(8, 8), "");
1125 static_assert(alignof(fit::function<float(int), 9>) == ExpectedAlignment(8, 16), "");
1126 static_assert(alignof(fit::function<float(int), 25>) == ExpectedAlignment(16, 16), "");
1127 static_assert(alignof(fit::inline_function<void(), 1>) == ExpectedAlignment(4, 8), "");
1128 static_assert(alignof(fit::inline_function<void(), 9>) == ExpectedAlignment(8, 16), "");
1129 static_assert(alignof(fit::callback<void(), 0>) == ExpectedAlignment(4, 8), "");
1130 static_assert(alignof(fit::callback<void(), 1>) == ExpectedAlignment(4, 8), "");
1131 static_assert(alignof(fit::callback<int(), 4>) == ExpectedAlignment(4, 8), "");
1132 static_assert(alignof(fit::callback<bool(), 8>) == ExpectedAlignment(8, 8), "");
1133 static_assert(alignof(fit::callback<float(int), 9>) == ExpectedAlignment(8, 16), "");
1134 static_assert(alignof(fit::callback<float(int), 25>) == ExpectedAlignment(16, 16), "");
1135 static_assert(alignof(fit::inline_callback<void(), 1>) == ExpectedAlignment(4, 8), "");
1136 static_assert(alignof(fit::inline_callback<void(), 9>) == ExpectedAlignment(8, 16), "");
1137 static_assert(alignof(fit::inline_callback<void(), 25>) == ExpectedAlignment(16, 16), "");
1138 
1139 namespace test_copy_move_constructions {
1140 
1141 template <typename F>
1142 class assert_move_only {
1143   static_assert(!std::is_copy_assignable<F>::value);
1144   static_assert(!std::is_copy_constructible<F>::value);
1145   static_assert(std::is_move_assignable<F>::value);
1146   static_assert(std::is_move_constructible<F>::value);
1147 
1148   // It seems that just testing `!std::is_copy_assignable<F>` is not enough,
1149   // as the `fit::function` class could use a perfect-forwarding mechanism
1150   // that still allows expressions of the form `fit::function func1 = func2`
1151   // to compile, even though `std::is_copy_assignable<F>` is false.
1152   template <typename T, typename = void>
1153   struct test : std::false_type {};
1154   template <typename T>
1155   struct test<T, std::void_t<decltype(T::v1 = T::v2)>> : std::true_type {};
1156 
1157   struct NoAssign {
1158     static F v1;
1159     static F v2;
1160   };
1161   static_assert(!test<NoAssign>::value);
1162 
1163   struct CanAssign {
1164     static int v1;
1165     static int v2;
1166   };
1167   static_assert(test<CanAssign>::value);
1168 
1169   template <typename T, typename = void>
1170   struct test_construct : std::false_type {};
1171   template <typename T>
1172   struct test_construct<T, std::void_t<decltype(T{std::declval<const T&>()})>> : std::true_type {};
1173 
1174   static_assert(!test_construct<F>::value);
1175   static_assert(test_construct<int>::value);
1176 };
1177 
1178 template class assert_move_only<fit::function<void()>>;
1179 template class assert_move_only<fit::callback<void()>>;
1180 
1181 }  // namespace test_copy_move_constructions
1182 
1183 namespace test_conversions {
1184 static_assert(std::is_convertible<Closure, fit::function<Closure>>::value, "");
1185 static_assert(std::is_convertible<BinaryOp, fit::function<BinaryOp>>::value, "");
1186 static_assert(std::is_assignable<fit::function<Closure>, Closure>::value, "");
1187 static_assert(std::is_assignable<fit::function<BinaryOp>, BinaryOp>::value, "");
1188 
1189 static_assert(std::is_assignable<fit::function<BooleanGenerator>, IntGenerator>::value, "");
1190 static_assert(std::is_assignable<fit::function<BuildableFromIntGenerator>, IntGenerator>::value,
1191               "");
1192 static_assert(!std::is_assignable<fit::function<IntGenerator>, BuildableFromIntGenerator>::value,
1193               "");
1194 
1195 static_assert(!std::is_convertible<BinaryOp, fit::function<Closure>>::value, "");
1196 static_assert(!std::is_convertible<Closure, fit::function<BinaryOp>>::value, "");
1197 static_assert(!std::is_assignable<fit::function<Closure>, BinaryOp>::value, "");
1198 static_assert(!std::is_assignable<fit::function<BinaryOp>, Closure>::value, "");
1199 
1200 static_assert(!std::is_convertible<ClosureWrongReturnType, fit::function<Closure>>::value, "");
1201 static_assert(!std::is_convertible<BinaryOpWrongReturnType, fit::function<BinaryOp>>::value, "");
1202 static_assert(!std::is_assignable<fit::function<Closure>, ClosureWrongReturnType>::value, "");
1203 static_assert(!std::is_assignable<fit::function<BinaryOp>, BinaryOpWrongReturnType>::value, "");
1204 
1205 static_assert(!std::is_convertible<void, fit::function<Closure>>::value, "");
1206 static_assert(!std::is_convertible<void, fit::function<BinaryOp>>::value, "");
1207 static_assert(!std::is_assignable<void, fit::function<Closure>>::value, "");
1208 static_assert(!std::is_assignable<void, fit::function<BinaryOp>>::value, "");
1209 
1210 static_assert(std::is_same<fit::function<BinaryOp>::result_type, int>::value, "");
1211 static_assert(std::is_same<fit::callback<BinaryOp>::result_type, int>::value, "");
1212 }  // namespace test_conversions
1213 
TEST(FunctionTests,closure_fit_function_Closure)1214 TEST(FunctionTests, closure_fit_function_Closure) { closure<fit::function<Closure>>(); }
TEST(FunctionTests,binary_op_fit_function_BinaryOp)1215 TEST(FunctionTests, binary_op_fit_function_BinaryOp) { binary_op<fit::function<BinaryOp>>(); }
TEST(FunctionTests,closure_fit_function_Closure_0u)1216 TEST(FunctionTests, closure_fit_function_Closure_0u) { closure<fit::function<Closure, 0u>>(); }
TEST(FunctionTests,binary_op_fit_function_BinaryOp_0u)1217 TEST(FunctionTests, binary_op_fit_function_BinaryOp_0u) {
1218   binary_op<fit::function<BinaryOp, 0u>>();
1219 }
TEST(FunctionTests,closure_fit_function_Closure_HugeCallableSize)1220 TEST(FunctionTests, closure_fit_function_Closure_HugeCallableSize) {
1221   closure<fit::function<Closure, HugeCallableSize>>();
1222 }
TEST(FunctionTests,binary_op_fit_function_BinaryOp_HugeCallableSize)1223 TEST(FunctionTests, binary_op_fit_function_BinaryOp_HugeCallableSize) {
1224   binary_op<fit::function<BinaryOp, HugeCallableSize>>();
1225 }
TEST(FunctionTests,closure_fit_inline_function_Closure_HugeCallableSize)1226 TEST(FunctionTests, closure_fit_inline_function_Closure_HugeCallableSize) {
1227   closure<fit::inline_function<Closure, HugeCallableSize>>();
1228 }
TEST(FunctionTests,binary_op_fit_inline_function_BinaryOp_HugeCallableSize)1229 TEST(FunctionTests, binary_op_fit_inline_function_BinaryOp_HugeCallableSize) {
1230   binary_op<fit::inline_function<BinaryOp, HugeCallableSize>>();
1231 }
TEST(FunctionTests,closure_fit_function_Closure_SingleObjectAllocator)1232 TEST(FunctionTests, closure_fit_function_Closure_SingleObjectAllocator) {
1233   closure<
1234       fit::function<Closure, fit::default_inline_target_size, SingleObjectAllocator<std::byte>>>();
1235 }
TEST(FunctionTests,binary_op_fit_function_BinaryOp_SingleObjectAllocator)1236 TEST(FunctionTests, binary_op_fit_function_BinaryOp_SingleObjectAllocator) {
1237   binary_op<
1238       fit::function<BinaryOp, fit::default_inline_target_size, SingleObjectAllocator<std::byte>>>();
1239 }
1240 
TEST(FunctionTests,bind_return_reference)1241 TEST(FunctionTests, bind_return_reference) {
1242   struct TestClass {
1243     int& member() { return member_; }
1244     int member_ = 0;
1245   };
1246 
1247   TestClass instance;
1248   // Ensure that references to the original values are returned, not copies.
1249   fit::function<int&()> func = fit::bind_member<&TestClass::member>(&instance);
1250   EXPECT_EQ(&func(), &instance.member_);
1251 
1252   fit::function<int&()> func_deprecated = fit::bind_member(&instance, &TestClass::member);
1253   EXPECT_EQ(&func_deprecated(), &instance.member_);
1254 }
1255 
1256 }  // namespace
1257