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::__anond79064650111::ConstFunctor45   int operator()(int a, int b) const { return a - b; }
46 };
47 
48 struct MutableFunctor {
operator ()absl::base_internal::__anond79064650111::MutableFunctor49   int operator()(int a, int b) { return a - b; }
50 };
51 
52 struct EphemeralFunctor {
operator ()absl::base_internal::__anond79064650111::EphemeralFunctor53   int operator()(int a, int b) && { return a - b; }
54 };
55 
56 struct OverloadedFunctor {
57   template <typename... Args>
operator ()absl::base_internal::__anond79064650111::OverloadedFunctor58   std::string operator()(const Args&... args) & {
59     return StrCat("&", args...);
60   }
61   template <typename... Args>
operator ()absl::base_internal::__anond79064650111::OverloadedFunctor62   std::string operator()(const Args&... args) const& {
63     return StrCat("const&", args...);
64   }
65   template <typename... Args>
operator ()absl::base_internal::__anond79064650111::OverloadedFunctor66   std::string operator()(const Args&... args) && {
67     return StrCat("&&", args...);
68   }
69 };
70 
71 struct Class {
Methodabsl::base_internal::__anond79064650111::Class72   int Method(int a, int b) { return a - b; }
ConstMethodabsl::base_internal::__anond79064650111::Class73   int ConstMethod(int a, int b) const { return a - b; }
RefMethodabsl::base_internal::__anond79064650111::Class74   int RefMethod(int a, int b) & { return a - b; }
RefRefMethodabsl::base_internal::__anond79064650111::Class75   int RefRefMethod(int a, int b) && { return a - b; }
NoExceptMethodabsl::base_internal::__anond79064650111::Class76   int NoExceptMethod(int a, int b) noexcept { return a - b; }
VolatileMethodabsl::base_internal::__anond79064650111::Class77   int VolatileMethod(int a, int b) volatile { return a - b; }
78 
79   int member;
80 };
81 
82 struct FlipFlop {
ConstMethodabsl::base_internal::__anond79064650111::FlipFlop83   int ConstMethod() const { return member; }
operator *absl::base_internal::__anond79064650111::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