1 // Copyright 2017 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/base/internal/invoke.h"
16
17 #include <functional>
18 #include <memory>
19 #include <string>
20 #include <utility>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/memory/memory.h"
25 #include "absl/strings/str_cat.h"
26
27 namespace absl {
28 ABSL_NAMESPACE_BEGIN
29 namespace base_internal {
30 namespace {
31
Function(int a,int b)32 int Function(int a, int b) { return a - b; }
33
VoidFunction(int & a,int & b)34 void VoidFunction(int& a, int& b) {
35 a += b;
36 b = a - b;
37 a -= b;
38 }
39
ZeroArgFunction()40 int ZeroArgFunction() { return -1937; }
41
Sink(std::unique_ptr<int> p)42 int Sink(std::unique_ptr<int> p) {
43 return *p;
44 }
45
Factory(int n)46 std::unique_ptr<int> Factory(int n) {
47 return make_unique<int>(n);
48 }
49
NoOp()50 void NoOp() {}
51
52 struct ConstFunctor {
operator ()absl::base_internal::__anon2b2eb2bf0111::ConstFunctor53 int operator()(int a, int b) const { return a - b; }
54 };
55
56 struct MutableFunctor {
operator ()absl::base_internal::__anon2b2eb2bf0111::MutableFunctor57 int operator()(int a, int b) { return a - b; }
58 };
59
60 struct EphemeralFunctor {
operator ()absl::base_internal::__anon2b2eb2bf0111::EphemeralFunctor61 int operator()(int a, int b) && { return a - b; }
62 };
63
64 struct OverloadedFunctor {
65 template <typename... Args>
operator ()absl::base_internal::__anon2b2eb2bf0111::OverloadedFunctor66 std::string operator()(const Args&... args) & {
67 return StrCat("&", args...);
68 }
69 template <typename... Args>
operator ()absl::base_internal::__anon2b2eb2bf0111::OverloadedFunctor70 std::string operator()(const Args&... args) const& {
71 return StrCat("const&", args...);
72 }
73 template <typename... Args>
operator ()absl::base_internal::__anon2b2eb2bf0111::OverloadedFunctor74 std::string operator()(const Args&... args) && {
75 return StrCat("&&", args...);
76 }
77 };
78
79 struct Class {
Methodabsl::base_internal::__anon2b2eb2bf0111::Class80 int Method(int a, int b) { return a - b; }
ConstMethodabsl::base_internal::__anon2b2eb2bf0111::Class81 int ConstMethod(int a, int b) const { return a - b; }
RefMethodabsl::base_internal::__anon2b2eb2bf0111::Class82 int RefMethod(int a, int b) & { return a - b; }
RefRefMethodabsl::base_internal::__anon2b2eb2bf0111::Class83 int RefRefMethod(int a, int b) && { return a - b; }
NoExceptMethodabsl::base_internal::__anon2b2eb2bf0111::Class84 int NoExceptMethod(int a, int b) noexcept { return a - b; }
VolatileMethodabsl::base_internal::__anon2b2eb2bf0111::Class85 int VolatileMethod(int a, int b) volatile { return a - b; }
86
87 int member;
88 };
89
90 struct FlipFlop {
ConstMethodabsl::base_internal::__anon2b2eb2bf0111::FlipFlop91 int ConstMethod() const { return member; }
operator *absl::base_internal::__anon2b2eb2bf0111::FlipFlop92 FlipFlop operator*() const { return {-member}; }
93
94 int member;
95 };
96
97 // CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
98 // on which one is valid.
99 template <typename F>
invoke(std::declval<const F &> ())100 decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
101 const F& f) {
102 return base_internal::invoke(f);
103 }
104
105 template <typename F>
CallMaybeWithArg(const F & f)106 decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
107 const F& f) {
108 return base_internal::invoke(f, 42);
109 }
110
TEST(InvokeTest,Function)111 TEST(InvokeTest, Function) {
112 EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
113 EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
114 }
115
TEST(InvokeTest,NonCopyableArgument)116 TEST(InvokeTest, NonCopyableArgument) {
117 EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
118 }
119
TEST(InvokeTest,NonCopyableResult)120 TEST(InvokeTest, NonCopyableResult) {
121 EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
122 }
123
TEST(InvokeTest,VoidResult)124 TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
125
TEST(InvokeTest,ConstFunctor)126 TEST(InvokeTest, ConstFunctor) {
127 EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
128 }
129
TEST(InvokeTest,MutableFunctor)130 TEST(InvokeTest, MutableFunctor) {
131 MutableFunctor f;
132 EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
133 EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
134 }
135
TEST(InvokeTest,EphemeralFunctor)136 TEST(InvokeTest, EphemeralFunctor) {
137 EphemeralFunctor f;
138 EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
139 EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
140 }
141
TEST(InvokeTest,OverloadedFunctor)142 TEST(InvokeTest, OverloadedFunctor) {
143 OverloadedFunctor f;
144 const OverloadedFunctor& cf = f;
145
146 EXPECT_EQ("&", base_internal::invoke(f));
147 EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
148
149 EXPECT_EQ("const&", base_internal::invoke(cf));
150 EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
151
152 EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
153
154 OverloadedFunctor f2;
155 EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
156 }
157
TEST(InvokeTest,ReferenceWrapper)158 TEST(InvokeTest, ReferenceWrapper) {
159 ConstFunctor cf;
160 MutableFunctor mf;
161 EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
162 EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
163 EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
164 }
165
TEST(InvokeTest,MemberFunction)166 TEST(InvokeTest, MemberFunction) {
167 std::unique_ptr<Class> p(new Class);
168 std::unique_ptr<const Class> cp(new Class);
169 std::unique_ptr<volatile Class> vp(new Class);
170
171 EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
172 EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
173 EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
174 EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
175 EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
176 EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
177 EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
178 2)); // NOLINT
179 EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
180 EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
181 EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
182
183 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
184 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
185 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
186
187 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
188 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
189 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
190
191 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
192 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
193 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
194 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
195 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
196 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
197
198 EXPECT_EQ(1,
199 base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
200 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
201 3, 2));
202 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
203 make_unique<const Class>(), 3, 2));
204 }
205
TEST(InvokeTest,DataMember)206 TEST(InvokeTest, DataMember) {
207 std::unique_ptr<Class> p(new Class{42});
208 std::unique_ptr<const Class> cp(new Class{42});
209 EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
210 EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
211 EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
212
213 base_internal::invoke(&Class::member, p) = 42;
214 base_internal::invoke(&Class::member, p.get()) = 42;
215
216 EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
217 EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
218 EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
219 }
220
TEST(InvokeTest,FlipFlop)221 TEST(InvokeTest, FlipFlop) {
222 FlipFlop obj = {42};
223 // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
224 // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
225 EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
226 EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
227 }
228
TEST(InvokeTest,SfinaeFriendly)229 TEST(InvokeTest, SfinaeFriendly) {
230 CallMaybeWithArg(NoOp);
231 EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
232 }
233
TEST(IsInvocableRTest,CallableExactMatch)234 TEST(IsInvocableRTest, CallableExactMatch) {
235 static_assert(
236 base_internal::is_invocable_r<int, decltype(Function), int, int>::value,
237 "Should be true for exact match of types on a free function");
238 }
239
TEST(IsInvocableRTest,CallableArgumentConversionMatch)240 TEST(IsInvocableRTest, CallableArgumentConversionMatch) {
241 static_assert(
242 base_internal::is_invocable_r<int, decltype(Function), char, int>::value,
243 "Should be true for convertible argument type");
244 }
245
TEST(IsInvocableRTest,CallableReturnConversionMatch)246 TEST(IsInvocableRTest, CallableReturnConversionMatch) {
247 static_assert(base_internal::is_invocable_r<double, decltype(Function), int,
248 int>::value,
249 "Should be true for convertible return type");
250 }
251
TEST(IsInvocableRTest,CallableReturnVoid)252 TEST(IsInvocableRTest, CallableReturnVoid) {
253 static_assert(base_internal::is_invocable_r<void, decltype(VoidFunction),
254 int&, int&>::value,
255 "Should be true for void expected and actual return types");
256 static_assert(
257 base_internal::is_invocable_r<void, decltype(Function), int, int>::value,
258 "Should be true for void expected and non-void actual return types");
259 }
260
TEST(IsInvocableRTest,CallableRefQualifierMismatch)261 TEST(IsInvocableRTest, CallableRefQualifierMismatch) {
262 static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
263 int&, const int&>::value,
264 "Should be false for reference constness mismatch");
265 static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
266 int&&, int&>::value,
267 "Should be false for reference value category mismatch");
268 }
269
TEST(IsInvocableRTest,CallableArgumentTypeMismatch)270 TEST(IsInvocableRTest, CallableArgumentTypeMismatch) {
271 static_assert(!base_internal::is_invocable_r<int, decltype(Function),
272 std::string, int>::value,
273 "Should be false for argument type mismatch");
274 }
275
TEST(IsInvocableRTest,CallableReturnTypeMismatch)276 TEST(IsInvocableRTest, CallableReturnTypeMismatch) {
277 static_assert(!base_internal::is_invocable_r<std::string, decltype(Function),
278 int, int>::value,
279 "Should be false for return type mismatch");
280 }
281
TEST(IsInvocableRTest,CallableTooFewArgs)282 TEST(IsInvocableRTest, CallableTooFewArgs) {
283 static_assert(
284 !base_internal::is_invocable_r<int, decltype(Function), int>::value,
285 "Should be false for too few arguments");
286 }
287
TEST(IsInvocableRTest,CallableTooManyArgs)288 TEST(IsInvocableRTest, CallableTooManyArgs) {
289 static_assert(!base_internal::is_invocable_r<int, decltype(Function), int,
290 int, int>::value,
291 "Should be false for too many arguments");
292 }
293
TEST(IsInvocableRTest,MemberFunctionAndReference)294 TEST(IsInvocableRTest, MemberFunctionAndReference) {
295 static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
296 Class&, int, int>::value,
297 "Should be true for exact match of types on a member function "
298 "and class reference");
299 }
300
TEST(IsInvocableRTest,MemberFunctionAndPointer)301 TEST(IsInvocableRTest, MemberFunctionAndPointer) {
302 static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
303 Class*, int, int>::value,
304 "Should be true for exact match of types on a member function "
305 "and class pointer");
306 }
307
TEST(IsInvocableRTest,DataMemberAndReference)308 TEST(IsInvocableRTest, DataMemberAndReference) {
309 static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
310 Class&>::value,
311 "Should be true for exact match of types on a data member and "
312 "class reference");
313 }
314
TEST(IsInvocableRTest,DataMemberAndPointer)315 TEST(IsInvocableRTest, DataMemberAndPointer) {
316 static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
317 Class*>::value,
318 "Should be true for exact match of types on a data member and "
319 "class pointer");
320 }
321
TEST(IsInvocableRTest,CallableZeroArgs)322 TEST(IsInvocableRTest, CallableZeroArgs) {
323 static_assert(
324 base_internal::is_invocable_r<int, decltype(ZeroArgFunction)>::value,
325 "Should be true for exact match for a zero-arg free function");
326 }
327
328 } // namespace
329 } // namespace base_internal
330 ABSL_NAMESPACE_END
331 } // namespace absl
332