1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #include <list> |
18 | |
19 | #include <folly/Function.h> |
20 | #include <folly/portability/GTest.h> |
21 | |
22 | using folly::Function; |
23 | using folly::FunctionRef; |
24 | |
25 | TEST(FunctionRef, Traits) { |
26 | static_assert(std::is_literal_type<FunctionRef<int(int)>>::value, "" ); |
27 | // Some earlier versions of libstdc++ lack these traits. Frustrating that |
28 | // the value of __GLIBCXX__ doesn't increase with version, but rather reflects |
29 | // release date, so some larger values of __GLIBCXX__ lack the traits while |
30 | // some smaller values have them. Can't figure out how to reliably test for the |
31 | // presence or absence of the traits. :-( |
32 | #if !defined(__GLIBCXX__) || __GNUC__ >= 5 |
33 | static_assert( |
34 | std::is_trivially_copy_constructible<FunctionRef<int(int)>>::value, "" ); |
35 | static_assert( |
36 | std::is_trivially_move_constructible<FunctionRef<int(int)>>::value, "" ); |
37 | static_assert( |
38 | std::is_trivially_constructible< |
39 | FunctionRef<int(int)>, |
40 | FunctionRef<int(int)>&>::value, |
41 | "" ); |
42 | static_assert( |
43 | std::is_trivially_copy_assignable<FunctionRef<int(int)>>::value, "" ); |
44 | static_assert( |
45 | std::is_trivially_move_assignable<FunctionRef<int(int)>>::value, "" ); |
46 | static_assert( |
47 | std::is_trivially_assignable< |
48 | FunctionRef<int(int)>, |
49 | FunctionRef<int(int)>&>::value, |
50 | "" ); |
51 | #endif |
52 | static_assert( |
53 | std::is_nothrow_copy_constructible<FunctionRef<int(int)>>::value, "" ); |
54 | static_assert( |
55 | std::is_nothrow_move_constructible<FunctionRef<int(int)>>::value, "" ); |
56 | static_assert( |
57 | std::is_nothrow_constructible< |
58 | FunctionRef<int(int)>, |
59 | FunctionRef<int(int)>&>::value, |
60 | "" ); |
61 | static_assert( |
62 | std::is_nothrow_copy_assignable<FunctionRef<int(int)>>::value, "" ); |
63 | static_assert( |
64 | std::is_nothrow_move_assignable<FunctionRef<int(int)>>::value, "" ); |
65 | static_assert( |
66 | std::is_nothrow_assignable< |
67 | FunctionRef<int(int)>, |
68 | FunctionRef<int(int)>&>::value, |
69 | "" ); |
70 | } |
71 | |
72 | TEST(FunctionRef, Simple) { |
73 | int x = 1000; |
74 | auto lambda = [&x](int v) { return x += v; }; |
75 | |
76 | FunctionRef<int(int)> fref = lambda; |
77 | EXPECT_EQ(1005, fref(5)); |
78 | EXPECT_EQ(1011, fref(6)); |
79 | EXPECT_EQ(1018, fref(7)); |
80 | |
81 | FunctionRef<int(int)> const cfref = lambda; |
82 | EXPECT_EQ(1023, cfref(5)); |
83 | EXPECT_EQ(1029, cfref(6)); |
84 | EXPECT_EQ(1036, cfref(7)); |
85 | |
86 | auto const& clambda = lambda; |
87 | |
88 | FunctionRef<int(int)> fcref = clambda; |
89 | EXPECT_EQ(1041, fcref(5)); |
90 | EXPECT_EQ(1047, fcref(6)); |
91 | EXPECT_EQ(1054, fcref(7)); |
92 | |
93 | FunctionRef<int(int)> const cfcref = clambda; |
94 | EXPECT_EQ(1059, cfcref(5)); |
95 | EXPECT_EQ(1065, cfcref(6)); |
96 | EXPECT_EQ(1072, cfcref(7)); |
97 | } |
98 | |
99 | TEST(FunctionRef, FunctionPtr) { |
100 | int (*funcptr)(int) = [](int v) { return v * v; }; |
101 | |
102 | FunctionRef<int(int)> fref = funcptr; |
103 | EXPECT_EQ(100, fref(10)); |
104 | EXPECT_EQ(121, fref(11)); |
105 | |
106 | FunctionRef<int(int)> const cfref = funcptr; |
107 | EXPECT_EQ(100, cfref(10)); |
108 | EXPECT_EQ(121, cfref(11)); |
109 | } |
110 | |
111 | TEST(FunctionRef, OverloadedFunctor) { |
112 | struct OverloadedFunctor { |
113 | // variant 1 |
114 | int operator()(int x) { |
115 | return 100 + 1 * x; |
116 | } |
117 | |
118 | // variant 2 (const-overload of v1) |
119 | int operator()(int x) const { |
120 | return 100 + 2 * x; |
121 | } |
122 | |
123 | // variant 3 |
124 | int operator()(int x, int) { |
125 | return 100 + 3 * x; |
126 | } |
127 | |
128 | // variant 4 (const-overload of v3) |
129 | int operator()(int x, int) const { |
130 | return 100 + 4 * x; |
131 | } |
132 | |
133 | // variant 5 (non-const, has no const-overload) |
134 | int operator()(int x, char const*) { |
135 | return 100 + 5 * x; |
136 | } |
137 | |
138 | // variant 6 (const only) |
139 | int operator()(int x, std::vector<int> const&) const { |
140 | return 100 + 6 * x; |
141 | } |
142 | }; |
143 | OverloadedFunctor of; |
144 | auto const& cof = of; |
145 | |
146 | FunctionRef<int(int)> variant1 = of; |
147 | EXPECT_EQ(100 + 1 * 15, variant1(15)); |
148 | FunctionRef<int(int)> const cvariant1 = of; |
149 | EXPECT_EQ(100 + 1 * 15, cvariant1(15)); |
150 | |
151 | FunctionRef<int(int)> variant2 = cof; |
152 | EXPECT_EQ(100 + 2 * 16, variant2(16)); |
153 | FunctionRef<int(int)> const cvariant2 = cof; |
154 | EXPECT_EQ(100 + 2 * 16, cvariant2(16)); |
155 | |
156 | FunctionRef<int(int, int)> variant3 = of; |
157 | EXPECT_EQ(100 + 3 * 17, variant3(17, 0)); |
158 | FunctionRef<int(int, int)> const cvariant3 = of; |
159 | EXPECT_EQ(100 + 3 * 17, cvariant3(17, 0)); |
160 | |
161 | FunctionRef<int(int, int)> variant4 = cof; |
162 | EXPECT_EQ(100 + 4 * 18, variant4(18, 0)); |
163 | FunctionRef<int(int, int)> const cvariant4 = cof; |
164 | EXPECT_EQ(100 + 4 * 18, cvariant4(18, 0)); |
165 | |
166 | FunctionRef<int(int, char const*)> variant5 = of; |
167 | EXPECT_EQ(100 + 5 * 19, variant5(19, "foo" )); |
168 | FunctionRef<int(int, char const*)> const cvariant5 = of; |
169 | EXPECT_EQ(100 + 5 * 19, cvariant5(19, "foo" )); |
170 | |
171 | FunctionRef<int(int, std::vector<int> const&)> variant6 = of; |
172 | EXPECT_EQ(100 + 6 * 20, variant6(20, {})); |
173 | EXPECT_EQ(100 + 6 * 20, variant6(20, {1, 2, 3})); |
174 | FunctionRef<int(int, std::vector<int> const&)> const cvariant6 = of; |
175 | EXPECT_EQ(100 + 6 * 20, cvariant6(20, {})); |
176 | EXPECT_EQ(100 + 6 * 20, cvariant6(20, {1, 2, 3})); |
177 | |
178 | FunctionRef<int(int, std::vector<int> const&)> variant6const = cof; |
179 | EXPECT_EQ(100 + 6 * 21, variant6const(21, {})); |
180 | FunctionRef<int(int, std::vector<int> const&)> const cvariant6const = cof; |
181 | EXPECT_EQ(100 + 6 * 21, cvariant6const(21, {})); |
182 | } |
183 | |
184 | TEST(FunctionRef, DefaultConstructAndAssign) { |
185 | FunctionRef<int(int, int)> fref; |
186 | |
187 | EXPECT_FALSE(fref); |
188 | EXPECT_THROW(fref(1, 2), std::bad_function_call); |
189 | |
190 | int (*func)(int, int) = [](int x, int y) { return 10 * x + y; }; |
191 | fref = func; |
192 | |
193 | EXPECT_TRUE(fref); |
194 | EXPECT_EQ(42, fref(4, 2)); |
195 | } |
196 | |
197 | template <typename ValueType> |
198 | class ForEach { |
199 | public: |
200 | template <typename InputIterator> |
201 | ForEach(InputIterator begin, InputIterator end) |
202 | : func_([begin, end](FunctionRef<void(ValueType)> f) { |
203 | for (auto it = begin; it != end; ++it) { |
204 | f(*it); |
205 | } |
206 | }) {} |
207 | |
208 | void operator()(FunctionRef<void(ValueType)> f) const { |
209 | func_(f); |
210 | } |
211 | |
212 | private: |
213 | Function<void(FunctionRef<void(ValueType)>) const> const func_; |
214 | }; |
215 | |
216 | TEST(FunctionRef, ForEach) { |
217 | std::list<int> s{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
218 | |
219 | int sum = 0; |
220 | |
221 | ForEach<int> fe{s.begin(), s.end()}; |
222 | |
223 | fe([&](int x) { sum += x; }); |
224 | |
225 | EXPECT_EQ(55, sum); |
226 | } |
227 | |