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 <functional>
6 
7 #include <lib/fit/function.h>
8 #include <lib/fit/function_traits.h>
9 #include <unittest/unittest.h>
10 
11 namespace {
12 
13 template <typename Callable, typename... Args>
invoke_with_defaults(Callable c,fit::parameter_pack<Args...>)14 void invoke_with_defaults(Callable c, fit::parameter_pack<Args...>) {
15     c(Args()...);
16 }
17 
18 template <typename Callable>
invoke_with_defaults(Callable c)19 void invoke_with_defaults(Callable c) {
20     invoke_with_defaults(std::move(c), typename fit::function_traits<Callable>::args{});
21 }
22 
arg_capture()23 bool arg_capture() {
24     BEGIN_TEST;
25 
26     int i = 0;
27     invoke_with_defaults([&] { i = 42; });
28     EXPECT_EQ(42, i);
29     invoke_with_defaults([&](int, float) { i = 54; });
30     EXPECT_EQ(54, i);
31 
32     END_TEST;
33 }
34 
35 // Performs static assertions against a function-like type of signature int(float, bool).
36 template <typename Callable>
37 struct TraitsTest {
38     using Traits = fit::function_traits<Callable>;
39 
40     static_assert(std::is_same_v<int(float, bool), typename Traits::signature>);
41     static_assert(std::is_same_v<int, typename Traits::return_type>);
42     static_assert(2 == Traits::args::size);
43     static_assert(std::is_same_v<float, typename Traits::args::template at<0>>);
44     static_assert(std::is_same_v<bool, typename Traits::args::template at<1>>);
45 };
46 
47 // compile-time test
48 namespace signature_traits {
49 using Traits = TraitsTest<int(float, bool)>::Traits;
50 } // namespace signature_traits
51 
52 // compile-time test
53 namespace function_pointer_traits {
54 using Traits = TraitsTest<int (*)(float, bool)>::Traits;
55 static_assert(std::is_same_v<int (*)(float, bool), Traits::type>);
56 } // namespace function_pointer_traits
57 
58 // compile-time test
59 namespace lambda_traits {
__anon751b94140402(float, bool) 60 auto lambda = [](float, bool) { return 0; };
61 using Traits = TraitsTest<decltype(lambda)>::Traits;
62 } // namespace lambda_traits
63 
64 template <typename Functor>
65 struct FunctorTraitsTest {
66     using Traits = typename TraitsTest<Functor>::Traits;
67     static_assert(std::is_same_v<Functor, typename Traits::type>);
68 };
69 
70 // compile-time test
71 namespace mutable_functor_traits {
72 struct MutableFunctor {
operator ()__anon751b94140111::mutable_functor_traits::MutableFunctor73     int operator()(float, bool) { return 0; }
74 };
75 using Traits = FunctorTraitsTest<MutableFunctor>::Traits;
76 } //namespace mutable_functor_traits
77 
78 // compile-time test
79 namespace fit_function_traits {
80 using Traits = FunctorTraitsTest<fit::function<int(float, bool)>>;
81 } // namespace fit_function_traits
82 
83 // compile-time test
84 namespace std_function_traits {
85 using Traits = FunctorTraitsTest<std::function<int(float, bool)>>;
86 } // namespace std_function_traits
87 
88 } // namespace
89 
90 BEGIN_TEST_CASE(function_traits_tests)
91 RUN_TEST(arg_capture)
92 // suppress -Wunneeded-internal-declaration
93 (void)lambda_traits::lambda;
94 END_TEST_CASE(function_traits_tests)
95