1 // Copyright 2019 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/functional/function_ref.h"
16
17 #include <functional>
18 #include <memory>
19
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include "absl/container/internal/test_instance_tracker.h"
23 #include "absl/memory/memory.h"
24
25 namespace absl {
26 ABSL_NAMESPACE_BEGIN
27 namespace {
28
RunFun(FunctionRef<void ()> f)29 void RunFun(FunctionRef<void()> f) { f(); }
30
TEST(FunctionRefTest,Lambda)31 TEST(FunctionRefTest, Lambda) {
32 bool ran = false;
33 RunFun([&] { ran = true; });
34 EXPECT_TRUE(ran);
35 }
36
Function()37 int Function() { return 1337; }
38
TEST(FunctionRefTest,Function1)39 TEST(FunctionRefTest, Function1) {
40 FunctionRef<int()> ref(&Function);
41 EXPECT_EQ(1337, ref());
42 }
43
TEST(FunctionRefTest,Function2)44 TEST(FunctionRefTest, Function2) {
45 FunctionRef<int()> ref(Function);
46 EXPECT_EQ(1337, ref());
47 }
48
NoExceptFunction()49 int NoExceptFunction() noexcept { return 1337; }
50
51 // TODO(jdennett): Add a test for noexcept member functions.
TEST(FunctionRefTest,NoExceptFunction)52 TEST(FunctionRefTest, NoExceptFunction) {
53 FunctionRef<int()> ref(NoExceptFunction);
54 EXPECT_EQ(1337, ref());
55 }
56
TEST(FunctionRefTest,ForwardsArgs)57 TEST(FunctionRefTest, ForwardsArgs) {
58 auto l = [](std::unique_ptr<int> i) { return *i; };
59 FunctionRef<int(std::unique_ptr<int>)> ref(l);
60 EXPECT_EQ(42, ref(absl::make_unique<int>(42)));
61 }
62
TEST(FunctionRef,ReturnMoveOnly)63 TEST(FunctionRef, ReturnMoveOnly) {
64 auto l = [] { return absl::make_unique<int>(29); };
65 FunctionRef<std::unique_ptr<int>()> ref(l);
66 EXPECT_EQ(29, *ref());
67 }
68
TEST(FunctionRef,ManyArgs)69 TEST(FunctionRef, ManyArgs) {
70 auto l = [](int a, int b, int c) { return a + b + c; };
71 FunctionRef<int(int, int, int)> ref(l);
72 EXPECT_EQ(6, ref(1, 2, 3));
73 }
74
TEST(FunctionRef,VoidResultFromNonVoidFunctor)75 TEST(FunctionRef, VoidResultFromNonVoidFunctor) {
76 bool ran = false;
77 auto l = [&]() -> int {
78 ran = true;
79 return 2;
80 };
81 FunctionRef<void()> ref(l);
82 ref();
83 EXPECT_TRUE(ran);
84 }
85
TEST(FunctionRef,CastFromDerived)86 TEST(FunctionRef, CastFromDerived) {
87 struct Base {};
88 struct Derived : public Base {};
89
90 Derived d;
91 auto l1 = [&](Base* b) { EXPECT_EQ(&d, b); };
92 FunctionRef<void(Derived*)> ref1(l1);
93 ref1(&d);
94
95 auto l2 = [&]() -> Derived* { return &d; };
96 FunctionRef<Base*()> ref2(l2);
97 EXPECT_EQ(&d, ref2());
98 }
99
TEST(FunctionRef,VoidResultFromNonVoidFuncton)100 TEST(FunctionRef, VoidResultFromNonVoidFuncton) {
101 FunctionRef<void()> ref(Function);
102 ref();
103 }
104
TEST(FunctionRef,MemberPtr)105 TEST(FunctionRef, MemberPtr) {
106 struct S {
107 int i;
108 };
109
110 S s{1100111};
111 auto mem_ptr = &S::i;
112 FunctionRef<int(const S& s)> ref(mem_ptr);
113 EXPECT_EQ(1100111, ref(s));
114 }
115
TEST(FunctionRef,MemberFun)116 TEST(FunctionRef, MemberFun) {
117 struct S {
118 int i;
119 int get_i() const { return i; }
120 };
121
122 S s{22};
123 auto mem_fun_ptr = &S::get_i;
124 FunctionRef<int(const S& s)> ref(mem_fun_ptr);
125 EXPECT_EQ(22, ref(s));
126 }
127
TEST(FunctionRef,MemberFunRefqualified)128 TEST(FunctionRef, MemberFunRefqualified) {
129 struct S {
130 int i;
131 int get_i() && { return i; }
132 };
133 auto mem_fun_ptr = &S::get_i;
134 S s{22};
135 FunctionRef<int(S && s)> ref(mem_fun_ptr);
136 EXPECT_EQ(22, ref(std::move(s)));
137 }
138
139 #if !defined(_WIN32) && defined(GTEST_HAS_DEATH_TEST)
140
TEST(FunctionRef,MemberFunRefqualifiedNull)141 TEST(FunctionRef, MemberFunRefqualifiedNull) {
142 struct S {
143 int i;
144 int get_i() && { return i; }
145 };
146 auto mem_fun_ptr = &S::get_i;
147 mem_fun_ptr = nullptr;
148 EXPECT_DEBUG_DEATH({ FunctionRef<int(S && s)> ref(mem_fun_ptr); }, "");
149 }
150
TEST(FunctionRef,NullMemberPtrAssertFails)151 TEST(FunctionRef, NullMemberPtrAssertFails) {
152 struct S {
153 int i;
154 };
155 using MemberPtr = int S::*;
156 MemberPtr mem_ptr = nullptr;
157 EXPECT_DEBUG_DEATH({ FunctionRef<int(const S& s)> ref(mem_ptr); }, "");
158 }
159
160 #endif // GTEST_HAS_DEATH_TEST
161
TEST(FunctionRef,CopiesAndMovesPerPassByValue)162 TEST(FunctionRef, CopiesAndMovesPerPassByValue) {
163 absl::test_internal::InstanceTracker tracker;
164 absl::test_internal::CopyableMovableInstance instance(0);
165 auto l = [](absl::test_internal::CopyableMovableInstance) {};
166 FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
167 ref(instance);
168 EXPECT_EQ(tracker.copies(), 1);
169 EXPECT_EQ(tracker.moves(), 1);
170 }
171
TEST(FunctionRef,CopiesAndMovesPerPassByRef)172 TEST(FunctionRef, CopiesAndMovesPerPassByRef) {
173 absl::test_internal::InstanceTracker tracker;
174 absl::test_internal::CopyableMovableInstance instance(0);
175 auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
176 FunctionRef<void(const absl::test_internal::CopyableMovableInstance&)> ref(l);
177 ref(instance);
178 EXPECT_EQ(tracker.copies(), 0);
179 EXPECT_EQ(tracker.moves(), 0);
180 }
181
TEST(FunctionRef,CopiesAndMovesPerPassByValueCallByMove)182 TEST(FunctionRef, CopiesAndMovesPerPassByValueCallByMove) {
183 absl::test_internal::InstanceTracker tracker;
184 absl::test_internal::CopyableMovableInstance instance(0);
185 auto l = [](absl::test_internal::CopyableMovableInstance) {};
186 FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
187 ref(std::move(instance));
188 EXPECT_EQ(tracker.copies(), 0);
189 EXPECT_EQ(tracker.moves(), 2);
190 }
191
TEST(FunctionRef,CopiesAndMovesPerPassByValueToRef)192 TEST(FunctionRef, CopiesAndMovesPerPassByValueToRef) {
193 absl::test_internal::InstanceTracker tracker;
194 absl::test_internal::CopyableMovableInstance instance(0);
195 auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
196 FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
197 ref(std::move(instance));
198 EXPECT_EQ(tracker.copies(), 0);
199 EXPECT_EQ(tracker.moves(), 1);
200 }
201
TEST(FunctionRef,PassByValueTypes)202 TEST(FunctionRef, PassByValueTypes) {
203 using absl::functional_internal::Invoker;
204 using absl::functional_internal::VoidPtr;
205 using absl::test_internal::CopyableMovableInstance;
206 struct Trivial {
207 void* p[2];
208 };
209 struct LargeTrivial {
210 void* p[3];
211 };
212
213 static_assert(std::is_same<Invoker<void, int>, void (*)(VoidPtr, int)>::value,
214 "Scalar types should be passed by value");
215 static_assert(
216 std::is_same<Invoker<void, Trivial>, void (*)(VoidPtr, Trivial)>::value,
217 "Small trivial types should be passed by value");
218 static_assert(std::is_same<Invoker<void, LargeTrivial>,
219 void (*)(VoidPtr, LargeTrivial &&)>::value,
220 "Large trivial types should be passed by rvalue reference");
221 static_assert(
222 std::is_same<Invoker<void, CopyableMovableInstance>,
223 void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
224 "Types with copy/move ctor should be passed by rvalue reference");
225
226 // References are passed as references.
227 static_assert(
228 std::is_same<Invoker<void, int&>, void (*)(VoidPtr, int&)>::value,
229 "Reference types should be preserved");
230 static_assert(
231 std::is_same<Invoker<void, CopyableMovableInstance&>,
232 void (*)(VoidPtr, CopyableMovableInstance&)>::value,
233 "Reference types should be preserved");
234 static_assert(
235 std::is_same<Invoker<void, CopyableMovableInstance&&>,
236 void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
237 "Reference types should be preserved");
238
239 // Make sure the address of an object received by reference is the same as the
240 // addess of the object passed by the caller.
241 {
242 LargeTrivial obj;
243 auto test = [&obj](LargeTrivial& input) { ASSERT_EQ(&input, &obj); };
244 absl::FunctionRef<void(LargeTrivial&)> ref(test);
245 ref(obj);
246 }
247
248 {
249 Trivial obj;
250 auto test = [&obj](Trivial& input) { ASSERT_EQ(&input, &obj); };
251 absl::FunctionRef<void(Trivial&)> ref(test);
252 ref(obj);
253 }
254 }
255
256 } // namespace
257 ABSL_NAMESPACE_END
258 } // namespace absl
259