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/traits.h>
9 #include <unittest/unittest.h>
10
11 namespace {
12
13 namespace test_void_t {
14 static_assert(std::is_same<fit::void_t<>, void>::value, "");
15 static_assert(std::is_same<fit::void_t<int>, void>::value, "");
16 static_assert(std::is_same<fit::void_t<int, int>, void>::value, "");
17 } // namespace test_void_t
18
19 namespace test_callables {
20 template <typename Callable, typename... Args>
invoke_with_defaults(Callable c,fit::parameter_pack<Args...>)21 void invoke_with_defaults(Callable c, fit::parameter_pack<Args...>) {
22 c(Args()...);
23 }
24
25 template <typename Callable>
invoke_with_defaults(Callable c)26 void invoke_with_defaults(Callable c) {
27 invoke_with_defaults(std::move(c), typename fit::callable_traits<Callable>::args{});
28 }
29
arg_capture()30 bool arg_capture() {
31 BEGIN_TEST;
32
33 int i = 0;
34 invoke_with_defaults([&] { i = 42; });
35 EXPECT_EQ(42, i);
36 invoke_with_defaults([&](int, float) { i = 54; });
37 EXPECT_EQ(54, i);
38
39 END_TEST;
40 }
41
42 // Performs static assertions against a function-like type of signature int(float, bool).
43 template <typename Callable>
44 struct CallableTraitsTest {
45 using Traits = fit::callable_traits<Callable>;
46
47 static_assert(std::is_same_v<int(float, bool), typename Traits::signature>, "");
48 static_assert(std::is_same_v<int, typename Traits::return_type>, "");
49 static_assert(2 == Traits::args::size, "");
50 static_assert(std::is_same_v<float, typename Traits::args::template at<0>>, "");
51 static_assert(std::is_same_v<bool, typename Traits::args::template at<1>>, "");
52 };
53
54 // compile-time test
55 namespace signature_traits {
56 using Traits = CallableTraitsTest<int(float, bool)>::Traits;
57 } // namespace signature_traits
58
59 // compile-time test
60 namespace function_pointer_traits {
61 using Traits = CallableTraitsTest<int (*)(float, bool)>::Traits;
62 static_assert(std::is_same_v<int (*)(float, bool), Traits::type>, "");
63 } // namespace function_pointer_traits
64
65 // compile-time test
66 namespace member_function_pointer_traits {
67 struct Object {
68 int method(float, bool);
69 };
70 using Traits = CallableTraitsTest<int (Object::*)(float, bool)>::Traits;
71 static_assert(std::is_same_v<Object, Traits::type>, "");
72 } // namespace member_function_pointer_traits
73
74 // compile-time test
75 namespace lambda_traits {
__anon89ec1b0f0402(float, bool) 76 auto lambda = [](float, bool) { return 0; };
77 using Traits = CallableTraitsTest<decltype(lambda)>::Traits;
78 } // namespace lambda_traits
79
80 template <typename Functor>
81 struct FunctorTraitsTest {
82 using Traits = typename CallableTraitsTest<Functor>::Traits;
83 static_assert(std::is_same_v<Functor, typename Traits::type>, "");
84 };
85
86 // compile-time test
87 namespace mutable_functor_traits {
88 struct MutableFunctor {
operator ()__anon89ec1b0f0111::test_callables::mutable_functor_traits::MutableFunctor89 int operator()(float, bool) { return 0; }
90 };
91 using Traits = FunctorTraitsTest<MutableFunctor>::Traits;
92 } //namespace mutable_functor_traits
93
94 // compile-time test
95 namespace fit_callable_traits {
96 using Traits = FunctorTraitsTest<fit::function<int(float, bool)>>;
97 } // namespace fit_callable_traits
98
99 // compile-time test
100 namespace std_callable_traits {
101 using Traits = FunctorTraitsTest<std::function<int(float, bool)>>;
102 } // namespace std_callable_traits
103
104 static_assert(!fit::is_callable<void>::value, "");
105 static_assert(!fit::is_callable<int>::value, "");
106 static_assert(!fit::is_callable<int(float, bool)>::value, "");
107 static_assert(fit::is_callable<int (*)(float, bool)>::value, "");
108 static_assert(fit::is_callable<int (member_function_pointer_traits::Object::*)(float, bool)>::value, "");
109 static_assert(fit::is_callable<decltype(lambda_traits::lambda)>::value, "");
110 static_assert(fit::is_callable<mutable_functor_traits::MutableFunctor>::value, "");
111 static_assert(fit::is_callable<fit::function<int(float, bool)>>::value, "");
112 static_assert(fit::is_callable<std::function<int(float, bool)>>::value, "");
113
114 } // namespace test_callables
115
116 } // namespace
117
118 BEGIN_TEST_CASE(traits_test)
119 RUN_TEST(test_callables::arg_capture)
120 // suppress -Wunneeded-internal-declaration
121 (void)test_callables::lambda_traits::lambda;
122 END_TEST_CASE(traits_test)
123