abseil-cpp/absl/base/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 
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 {
29 namespace base_internal {
30 namespace {
31 
32 int Function(int a, int b) { return a - b; }
33 
34 void VoidFunction(int& a, int& b) {
35  a += b;
36  b = a - b;
37  a -= b;
38 }
39 
40 int ZeroArgFunction() { return -1937; }
41 
42 int Sink(std::unique_ptr<int> p) {
43  return *p;
44 }
45 
46 std::unique_ptr<int> Factory(int n) {
47  return make_unique<int>(n);
48 }
49 
50 void NoOp() {}
51 
52 struct ConstFunctor {
53  int operator()(int a, int b) const { return a - b; }
54 };
55 
56 struct MutableFunctor {
57  int operator()(int a, int b) { return a - b; }
58 };
59 
60 struct EphemeralFunctor {
61  int operator()(int a, int b) && { return a - b; }
62 };
63 
64 struct 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 
79 struct Class {
80  int Method(int a, int b) { return a - b; }
81  int ConstMethod(int a, int b) const { return a - b; }
82  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; }
86 
87  int member;
88 };
89 
90 struct FlipFlop {
91  int ConstMethod() const { return member; }
92  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>
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>
106 decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
107  const F& f) {
108  return base_internal::invoke(f, 42);
109 }
110 
111 TEST(InvokeTest, Function) {
114 }
115 
116 TEST(InvokeTest, NonCopyableArgument) {
117  EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
118 }
119 
120 TEST(InvokeTest, NonCopyableResult) {
122 }
123 
124 TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
125 
126 TEST(InvokeTest, ConstFunctor) {
127  EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
128 }
129 
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 
136 TEST(InvokeTest, EphemeralFunctor) {
137  EphemeralFunctor f;
139  EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
140 }
141 
142 TEST(InvokeTest, OverloadedFunctor) {
143  OverloadedFunctor f;
144  const OverloadedFunctor& cf = f;
145 
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 
153 
154  OverloadedFunctor f2;
155  EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
156 }
157 
158 TEST(InvokeTest, ReferenceWrapper) {
159  ConstFunctor cf;
160  MutableFunctor mf;
161  EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
164 }
165 
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 
172  EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 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 
206 TEST(InvokeTest, DataMember) {
207  std::unique_ptr<Class> p(new Class{42});
208  std::unique_ptr<const Class> cp(new Class{42});
212 
214  base_internal::invoke(&Class::member, p.get()) = 42;
215 
219 }
220 
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));
227 }
228 
229 TEST(InvokeTest, SfinaeFriendly) {
230  CallMaybeWithArg(NoOp);
231  EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
232 }
233 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
331 } // namespace absl
obj
OPENSSL_EXPORT const ASN1_OBJECT * obj
Definition: x509.h:1671
testing::Pointee
internal::PointeeMatcher< InnerMatcher > Pointee(const InnerMatcher &inner_matcher)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8691
const
#define const
Definition: bloaty/third_party/zlib/zconf.h:230
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
EXPECT_THAT
#define EXPECT_THAT(value, matcher)
NoOp
Definition: bm_call_create.cc:477
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
xds_manager.p
p
Definition: xds_manager.py:60
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
absl::operator*
uint128 operator*(uint128 lhs, uint128 rhs)
Definition: abseil-cpp/absl/numeric/int128.h:977
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
hpack_encoder_fixtures::Args
Args({0, 16384})
Method
struct Method Method
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:661
member
int member
Definition: abseil-cpp/absl/base/invoke_test.cc:87
ref
unsigned ref
Definition: cxa_demangle.cpp:4909
absl::base_internal::TEST
TEST(ExponentialBiasedTest, CoinTossDemoWithGetSkipCount)
Definition: bloaty/third_party/abseil-cpp/absl/base/internal/exponential_biased_test.cc:117
benchmark::internal::Function
void() Function(State &)
Definition: benchmark/include/benchmark/benchmark.h:826
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
value
const char * value
Definition: hpack_parser_table.cc:165
absl::base_internal::is_invocable_r
IsInvocableRImpl< void, R, F, Args... > is_invocable_r
Definition: abseil-cpp/absl/base/internal/invoke.h:233
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
xds_manager.f2
f2
Definition: xds_manager.py:85
absl::base_internal::invoke
invoke_result_t< F, Args... > invoke(F &&f, Args &&... args)
Definition: abseil-cpp/absl/base/internal/invoke.h:211


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:08