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