blob: 7be26f649f380e6a4f7d30e99a74054e2ffec4b2 [file] [log] [blame]
mistergc2e75482017-09-19 16:54:40 -04001// 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//
nik727338b70432019-03-08 10:27:53 -05007// https://www.apache.org/licenses/LICENSE-2.0
mistergc2e75482017-09-19 16:54:40 -04008//
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>
Abseil Team53c239d2017-09-19 17:15:26 -070020#include <utility>
mistergc2e75482017-09-19 16:54:40 -040021
22#include "gmock/gmock.h"
23#include "gtest/gtest.h"
24#include "absl/memory/memory.h"
25#include "absl/strings/str_cat.h"
26
27namespace absl {
Abseil Team1e39f862019-12-10 09:03:32 -080028ABSL_NAMESPACE_BEGIN
mistergc2e75482017-09-19 16:54:40 -040029namespace base_internal {
30namespace {
31
32int Function(int a, int b) { return a - b; }
33
Dino Radakovic0bc4bc22022-05-26 08:50:21 -070034void VoidFunction(int& a, int& b) {
35 a += b;
36 b = a - b;
37 a -= b;
38}
39
40int ZeroArgFunction() { return -1937; }
41
mistergc2e75482017-09-19 16:54:40 -040042int Sink(std::unique_ptr<int> p) {
43 return *p;
44}
45
46std::unique_ptr<int> Factory(int n) {
47 return make_unique<int>(n);
48}
49
50void NoOp() {}
51
52struct ConstFunctor {
53 int operator()(int a, int b) const { return a - b; }
54};
55
56struct MutableFunctor {
57 int operator()(int a, int b) { return a - b; }
58};
59
60struct EphemeralFunctor {
61 int operator()(int a, int b) && { return a - b; }
62};
63
64struct OverloadedFunctor {
65 template <typename... Args>
66 std::string operator()(const Args&... args) & {
67 return StrCat("&", args...);
68 }
69 template <typename... Args>
70 std::string operator()(const Args&... args) const& {
71 return StrCat("const&", args...);
72 }
73 template <typename... Args>
74 std::string operator()(const Args&... args) && {
75 return StrCat("&&", args...);
76 }
77};
78
79struct Class {
80 int Method(int a, int b) { return a - b; }
81 int ConstMethod(int a, int b) const { return a - b; }
Abseil Teamc5c4db42019-08-05 11:32:04 -070082 int RefMethod(int a, int b) & { return a - b; }
83 int RefRefMethod(int a, int b) && { return a - b; }
84 int NoExceptMethod(int a, int b) noexcept { return a - b; }
85 int VolatileMethod(int a, int b) volatile { return a - b; }
mistergc2e75482017-09-19 16:54:40 -040086
87 int member;
88};
89
90struct FlipFlop {
91 int ConstMethod() const { return member; }
92 FlipFlop operator*() const { return {-member}; }
93
94 int member;
95};
96
Abseil Team10cb35e2020-06-22 10:03:06 -070097// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
mistergc2e75482017-09-19 16:54:40 -040098// on which one is valid.
99template <typename F>
Abseil Team10cb35e2020-06-22 10:03:06 -0700100decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
101 const F& f) {
102 return base_internal::invoke(f);
mistergc2e75482017-09-19 16:54:40 -0400103}
104
105template <typename F>
Abseil Team10cb35e2020-06-22 10:03:06 -0700106decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
107 const F& f) {
108 return base_internal::invoke(f, 42);
mistergc2e75482017-09-19 16:54:40 -0400109}
110
111TEST(InvokeTest, Function) {
Abseil Team10cb35e2020-06-22 10:03:06 -0700112 EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
113 EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
mistergc2e75482017-09-19 16:54:40 -0400114}
115
116TEST(InvokeTest, NonCopyableArgument) {
Abseil Team10cb35e2020-06-22 10:03:06 -0700117 EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
mistergc2e75482017-09-19 16:54:40 -0400118}
119
120TEST(InvokeTest, NonCopyableResult) {
Abseil Team10cb35e2020-06-22 10:03:06 -0700121 EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
mistergc2e75482017-09-19 16:54:40 -0400122}
123
Abseil Team10cb35e2020-06-22 10:03:06 -0700124TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
mistergc2e75482017-09-19 16:54:40 -0400125
126TEST(InvokeTest, ConstFunctor) {
Abseil Team10cb35e2020-06-22 10:03:06 -0700127 EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
mistergc2e75482017-09-19 16:54:40 -0400128}
129
130TEST(InvokeTest, MutableFunctor) {
131 MutableFunctor f;
Abseil Team10cb35e2020-06-22 10:03:06 -0700132 EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
133 EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
mistergc2e75482017-09-19 16:54:40 -0400134}
135
136TEST(InvokeTest, EphemeralFunctor) {
137 EphemeralFunctor f;
Abseil Team10cb35e2020-06-22 10:03:06 -0700138 EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
139 EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
mistergc2e75482017-09-19 16:54:40 -0400140}
141
142TEST(InvokeTest, OverloadedFunctor) {
143 OverloadedFunctor f;
144 const OverloadedFunctor& cf = f;
145
Abseil Team10cb35e2020-06-22 10:03:06 -0700146 EXPECT_EQ("&", base_internal::invoke(f));
147 EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
mistergc2e75482017-09-19 16:54:40 -0400148
Abseil Team10cb35e2020-06-22 10:03:06 -0700149 EXPECT_EQ("const&", base_internal::invoke(cf));
150 EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
mistergc2e75482017-09-19 16:54:40 -0400151
Abseil Team10cb35e2020-06-22 10:03:06 -0700152 EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
153
154 OverloadedFunctor f2;
155 EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
mistergc2e75482017-09-19 16:54:40 -0400156}
157
158TEST(InvokeTest, ReferenceWrapper) {
159 ConstFunctor cf;
160 MutableFunctor mf;
Abseil Team10cb35e2020-06-22 10:03:06 -0700161 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));
mistergc2e75482017-09-19 16:54:40 -0400164}
165
166TEST(InvokeTest, MemberFunction) {
167 std::unique_ptr<Class> p(new Class);
168 std::unique_ptr<const Class> cp(new Class);
Abseil Teamc5c4db42019-08-05 11:32:04 -0700169 std::unique_ptr<volatile Class> vp(new Class);
170
Abseil Team10cb35e2020-06-22 10:03:06 -0700171 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));
mistergc2e75482017-09-19 16:54:40 -0400182
Abseil Team10cb35e2020-06-22 10:03:06 -0700183 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));
mistergc2e75482017-09-19 16:54:40 -0400186
Abseil Team10cb35e2020-06-22 10:03:06 -0700187 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));
mistergc2e75482017-09-19 16:54:40 -0400190
Abseil Team10cb35e2020-06-22 10:03:06 -0700191 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));
Abseil Teamc5c4db42019-08-05 11:32:04 -0700197
Abseil Team10cb35e2020-06-22 10:03:06 -0700198 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));
mistergc2e75482017-09-19 16:54:40 -0400204}
205
206TEST(InvokeTest, DataMember) {
207 std::unique_ptr<Class> p(new Class{42});
208 std::unique_ptr<const Class> cp(new Class{42});
Abseil Team10cb35e2020-06-22 10:03:06 -0700209 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()));
mistergc2e75482017-09-19 16:54:40 -0400212
Abseil Team10cb35e2020-06-22 10:03:06 -0700213 base_internal::invoke(&Class::member, p) = 42;
214 base_internal::invoke(&Class::member, p.get()) = 42;
mistergc2e75482017-09-19 16:54:40 -0400215
Abseil Team10cb35e2020-06-22 10:03:06 -0700216 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()));
mistergc2e75482017-09-19 16:54:40 -0400219}
220
221TEST(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.
Abseil Team10cb35e2020-06-22 10:03:06 -0700225 EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
226 EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
mistergc2e75482017-09-19 16:54:40 -0400227}
228
229TEST(InvokeTest, SfinaeFriendly) {
230 CallMaybeWithArg(NoOp);
231 EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
232}
233
Dino Radakovic0bc4bc22022-05-26 08:50:21 -0700234TEST(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
240TEST(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
246TEST(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
252TEST(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
261TEST(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
270TEST(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
276TEST(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
282TEST(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
288TEST(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
294TEST(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
301TEST(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
308TEST(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
315TEST(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
322TEST(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
mistergc2e75482017-09-19 16:54:40 -0400328} // namespace
329} // namespace base_internal
Abseil Team1e39f862019-12-10 09:03:32 -0800330ABSL_NAMESPACE_END
mistergc2e75482017-09-19 16:54:40 -0400331} // namespace absl