invoke_test.cc
Go to the documentation of this file.
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 
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 namespace base_internal {
29 namespace {
30 
31 int Function(int a, int b) { return a - b; }
32 
33 int Sink(std::unique_ptr<int> p) {
34  return *p;
35 }
36 
37 std::unique_ptr<int> Factory(int n) {
38  return make_unique<int>(n);
39 }
40 
41 void NoOp() {}
42 
43 struct ConstFunctor {
44  int operator()(int a, int b) const { return a - b; }
45 };
46 
47 struct MutableFunctor {
48  int operator()(int a, int b) { return a - b; }
49 };
50 
51 struct EphemeralFunctor {
52  int operator()(int a, int b) && { return a - b; }
53 };
54 
55 struct OverloadedFunctor {
56  template <typename... Args>
57  std::string operator()(const Args&... args) & {
58  return StrCat("&", args...);
59  }
60  template <typename... Args>
61  std::string operator()(const Args&... args) const& {
62  return StrCat("const&", args...);
63  }
64  template <typename... Args>
65  std::string operator()(const Args&... args) && {
66  return StrCat("&&", args...);
67  }
68 };
69 
70 struct Class {
71  int Method(int a, int b) { return a - b; }
72  int ConstMethod(int a, int b) const { return a - b; }
73 
74  int member;
75 };
76 
77 struct FlipFlop {
78  int ConstMethod() const { return member; }
79  FlipFlop operator*() const { return {-member}; }
80 
81  int member;
82 };
83 
84 // CallMaybeWithArg(f) resolves either to Invoke(f) or Invoke(f, 42), depending
85 // on which one is valid.
86 template <typename F>
87 decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
88  return Invoke(f);
89 }
90 
91 template <typename F>
92 decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
93  return Invoke(f, 42);
94 }
95 
96 TEST(InvokeTest, Function) {
97  EXPECT_EQ(1, Invoke(Function, 3, 2));
98  EXPECT_EQ(1, Invoke(&Function, 3, 2));
99 }
100 
101 TEST(InvokeTest, NonCopyableArgument) {
102  EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
103 }
104 
105 TEST(InvokeTest, NonCopyableResult) {
106  EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
107 }
108 
109 TEST(InvokeTest, VoidResult) {
110  Invoke(NoOp);
111 }
112 
113 TEST(InvokeTest, ConstFunctor) {
114  EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
115 }
116 
117 TEST(InvokeTest, MutableFunctor) {
118  MutableFunctor f;
119  EXPECT_EQ(1, Invoke(f, 3, 2));
120  EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
121 }
122 
123 TEST(InvokeTest, EphemeralFunctor) {
124  EphemeralFunctor f;
125  EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
126  EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
127 }
128 
129 TEST(InvokeTest, OverloadedFunctor) {
130  OverloadedFunctor f;
131  const OverloadedFunctor& cf = f;
132 
133  EXPECT_EQ("&", Invoke(f));
134  EXPECT_EQ("& 42", Invoke(f, " 42"));
135 
136  EXPECT_EQ("const&", Invoke(cf));
137  EXPECT_EQ("const& 42", Invoke(cf, " 42"));
138 
139  EXPECT_EQ("&&", Invoke(std::move(f)));
140  EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
141 }
142 
143 TEST(InvokeTest, ReferenceWrapper) {
144  ConstFunctor cf;
145  MutableFunctor mf;
146  EXPECT_EQ(1, Invoke(std::cref(cf), 3, 2));
147  EXPECT_EQ(1, Invoke(std::ref(cf), 3, 2));
148  EXPECT_EQ(1, Invoke(std::ref(mf), 3, 2));
149 }
150 
151 TEST(InvokeTest, MemberFunction) {
152  std::unique_ptr<Class> p(new Class);
153  std::unique_ptr<const Class> cp(new Class);
154  EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
155  EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
156 
157  EXPECT_EQ(1, Invoke(&Class::ConstMethod, p, 3, 2));
158  EXPECT_EQ(1, Invoke(&Class::ConstMethod, p.get(), 3, 2));
159  EXPECT_EQ(1, Invoke(&Class::ConstMethod, *p, 3, 2));
160 
161  EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp, 3, 2));
162  EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp.get(), 3, 2));
163  EXPECT_EQ(1, Invoke(&Class::ConstMethod, *cp, 3, 2));
164 
165  EXPECT_EQ(1, Invoke(&Class::Method, make_unique<Class>(), 3, 2));
166  EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<Class>(), 3, 2));
167  EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<const Class>(), 3, 2));
168 }
169 
170 TEST(InvokeTest, DataMember) {
171  std::unique_ptr<Class> p(new Class{42});
172  std::unique_ptr<const Class> cp(new Class{42});
173  EXPECT_EQ(42, Invoke(&Class::member, p));
174  EXPECT_EQ(42, Invoke(&Class::member, *p));
175  EXPECT_EQ(42, Invoke(&Class::member, p.get()));
176 
177  Invoke(&Class::member, p) = 42;
178  Invoke(&Class::member, p.get()) = 42;
179 
180  EXPECT_EQ(42, Invoke(&Class::member, cp));
181  EXPECT_EQ(42, Invoke(&Class::member, *cp));
182  EXPECT_EQ(42, Invoke(&Class::member, cp.get()));
183 }
184 
185 TEST(InvokeTest, FlipFlop) {
186  FlipFlop obj = {42};
187  // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
188  // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
189  EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
190  EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
191 }
192 
193 TEST(InvokeTest, SfinaeFriendly) {
194  CallMaybeWithArg(NoOp);
195  EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
196 }
197 
198 } // namespace
199 } // namespace base_internal
200 } // namespace absl
TEST(NotificationTest, SanityTest)
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: str_cat.cc:98
Definition: algorithm.h:29
uint128 operator*(uint128 lhs, uint128 rhs)
Definition: int128.h:671
int member
Definition: invoke_test.cc:74
InvokeT< F, Args... > Invoke(F &&f, Args &&... args)
Definition: invoke.h:181
uint64_t b
Definition: layout_test.cc:50
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: utility.h:219


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:19