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
Sink(std::unique_ptr<int> p)34 int Sink(std::unique_ptr<int> p) {
35 return *p;
36 }
37
Factory(int n)38 std::unique_ptr<int> Factory(int n) {
39 return make_unique<int>(n);
40 }
41
NoOp()42 void NoOp() {}
43
44 struct ConstFunctor {
operator ()absl::base_internal::__anon789ab8900111::ConstFunctor45 int operator()(int a, int b) const { return a - b; }
46 };
47
48 struct MutableFunctor {
operator ()absl::base_internal::__anon789ab8900111::MutableFunctor49 int operator()(int a, int b) { return a - b; }
50 };
51
52 struct EphemeralFunctor {
operator ()absl::base_internal::__anon789ab8900111::EphemeralFunctor53 int operator()(int a, int b) && { return a - b; }
54 };
55
56 struct OverloadedFunctor {
57 template <typename... Args>
operator ()absl::base_internal::__anon789ab8900111::OverloadedFunctor58 std::string operator()(const Args&... args) & {
59 return StrCat("&", args...);
60 }
61 template <typename... Args>
operator ()absl::base_internal::__anon789ab8900111::OverloadedFunctor62 std::string operator()(const Args&... args) const& {
63 return StrCat("const&", args...);
64 }
65 template <typename... Args>
operator ()absl::base_internal::__anon789ab8900111::OverloadedFunctor66 std::string operator()(const Args&... args) && {
67 return StrCat("&&", args...);
68 }
69 };
70
71 struct Class {
Methodabsl::base_internal::__anon789ab8900111::Class72 int Method(int a, int b) { return a - b; }
ConstMethodabsl::base_internal::__anon789ab8900111::Class73 int ConstMethod(int a, int b) const { return a - b; }
RefMethodabsl::base_internal::__anon789ab8900111::Class74 int RefMethod(int a, int b) & { return a - b; }
RefRefMethodabsl::base_internal::__anon789ab8900111::Class75 int RefRefMethod(int a, int b) && { return a - b; }
NoExceptMethodabsl::base_internal::__anon789ab8900111::Class76 int NoExceptMethod(int a, int b) noexcept { return a - b; }
VolatileMethodabsl::base_internal::__anon789ab8900111::Class77 int VolatileMethod(int a, int b) volatile { return a - b; }
78
79 int member;
80 };
81
82 struct FlipFlop {
ConstMethodabsl::base_internal::__anon789ab8900111::FlipFlop83 int ConstMethod() const { return member; }
operator *absl::base_internal::__anon789ab8900111::FlipFlop84 FlipFlop operator*() const { return {-member}; }
85
86 int member;
87 };
88
89 // CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
90 // on which one is valid.
91 template <typename F>
invoke(std::declval<const F &> ())92 decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
93 const F& f) {
94 return base_internal::invoke(f);
95 }
96
97 template <typename F>
CallMaybeWithArg(const F & f)98 decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
99 const F& f) {
100 return base_internal::invoke(f, 42);
101 }
102
TEST(InvokeTest,Function)103 TEST(InvokeTest, Function) {
104 EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
105 EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
106 }
107
TEST(InvokeTest,NonCopyableArgument)108 TEST(InvokeTest, NonCopyableArgument) {
109 EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
110 }
111
TEST(InvokeTest,NonCopyableResult)112 TEST(InvokeTest, NonCopyableResult) {
113 EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
114 }
115
TEST(InvokeTest,VoidResult)116 TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
117
TEST(InvokeTest,ConstFunctor)118 TEST(InvokeTest, ConstFunctor) {
119 EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
120 }
121
TEST(InvokeTest,MutableFunctor)122 TEST(InvokeTest, MutableFunctor) {
123 MutableFunctor f;
124 EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
125 EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
126 }
127
TEST(InvokeTest,EphemeralFunctor)128 TEST(InvokeTest, EphemeralFunctor) {
129 EphemeralFunctor f;
130 EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
131 EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
132 }
133
TEST(InvokeTest,OverloadedFunctor)134 TEST(InvokeTest, OverloadedFunctor) {
135 OverloadedFunctor f;
136 const OverloadedFunctor& cf = f;
137
138 EXPECT_EQ("&", base_internal::invoke(f));
139 EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
140
141 EXPECT_EQ("const&", base_internal::invoke(cf));
142 EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
143
144 EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
145
146 OverloadedFunctor f2;
147 EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
148 }
149
TEST(InvokeTest,ReferenceWrapper)150 TEST(InvokeTest, ReferenceWrapper) {
151 ConstFunctor cf;
152 MutableFunctor mf;
153 EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
154 EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
155 EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
156 }
157
TEST(InvokeTest,MemberFunction)158 TEST(InvokeTest, MemberFunction) {
159 std::unique_ptr<Class> p(new Class);
160 std::unique_ptr<const Class> cp(new Class);
161 std::unique_ptr<volatile Class> vp(new Class);
162
163 EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
164 EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
165 EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
166 EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
167 EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
168 EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
169 EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
170 2)); // NOLINT
171 EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
172 EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
173 EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
174
175 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
176 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
177 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
178
179 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
180 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
181 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
182
183 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
184 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
185 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
186 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
187 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
188 EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
189
190 EXPECT_EQ(1,
191 base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
192 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
193 3, 2));
194 EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
195 make_unique<const Class>(), 3, 2));
196 }
197
TEST(InvokeTest,DataMember)198 TEST(InvokeTest, DataMember) {
199 std::unique_ptr<Class> p(new Class{42});
200 std::unique_ptr<const Class> cp(new Class{42});
201 EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
202 EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
203 EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
204
205 base_internal::invoke(&Class::member, p) = 42;
206 base_internal::invoke(&Class::member, p.get()) = 42;
207
208 EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
209 EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
210 EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
211 }
212
TEST(InvokeTest,FlipFlop)213 TEST(InvokeTest, FlipFlop) {
214 FlipFlop obj = {42};
215 // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
216 // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
217 EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
218 EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
219 }
220
TEST(InvokeTest,SfinaeFriendly)221 TEST(InvokeTest, SfinaeFriendly) {
222 CallMaybeWithArg(NoOp);
223 EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
224 }
225
226 } // namespace
227 } // namespace base_internal
228 ABSL_NAMESPACE_END
229 } // namespace absl
230