summaryrefslogtreecommitdiff
path: root/absl/base/invoke_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/base/invoke_test.cc')
-rw-r--r--absl/base/invoke_test.cc238
1 files changed, 173 insertions, 65 deletions
diff --git a/absl/base/invoke_test.cc b/absl/base/invoke_test.cc
index 6aa613c9..7be26f64 100644
--- a/absl/base/invoke_test.cc
+++ b/absl/base/invoke_test.cc
@@ -31,6 +31,14 @@ namespace {
int Function(int a, int b) { return a - b; }
+void VoidFunction(int& a, int& b) {
+ a += b;
+ b = a - b;
+ a -= b;
+}
+
+int ZeroArgFunction() { return -1937; }
+
int Sink(std::unique_ptr<int> p) {
return *p;
}
@@ -86,71 +94,73 @@ struct FlipFlop {
int member;
};
-// CallMaybeWithArg(f) resolves either to Invoke(f) or Invoke(f, 42), depending
+// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
// on which one is valid.
template <typename F>
-decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
- return Invoke(f);
+decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
+ const F& f) {
+ return base_internal::invoke(f);
}
template <typename F>
-decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
- return Invoke(f, 42);
+decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
+ const F& f) {
+ return base_internal::invoke(f, 42);
}
TEST(InvokeTest, Function) {
- EXPECT_EQ(1, Invoke(Function, 3, 2));
- EXPECT_EQ(1, Invoke(&Function, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
}
TEST(InvokeTest, NonCopyableArgument) {
- EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
+ EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
}
TEST(InvokeTest, NonCopyableResult) {
- EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
+ EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
}
-TEST(InvokeTest, VoidResult) {
- Invoke(NoOp);
-}
+TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
TEST(InvokeTest, ConstFunctor) {
- EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
}
TEST(InvokeTest, MutableFunctor) {
MutableFunctor f;
- EXPECT_EQ(1, Invoke(f, 3, 2));
- EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
}
TEST(InvokeTest, EphemeralFunctor) {
EphemeralFunctor f;
- EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
- EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
}
TEST(InvokeTest, OverloadedFunctor) {
OverloadedFunctor f;
const OverloadedFunctor& cf = f;
- EXPECT_EQ("&", Invoke(f));
- EXPECT_EQ("& 42", Invoke(f, " 42"));
+ EXPECT_EQ("&", base_internal::invoke(f));
+ EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
+
+ EXPECT_EQ("const&", base_internal::invoke(cf));
+ EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
- EXPECT_EQ("const&", Invoke(cf));
- EXPECT_EQ("const& 42", Invoke(cf, " 42"));
+ EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
- EXPECT_EQ("&&", Invoke(std::move(f)));
- EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
+ OverloadedFunctor f2;
+ EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
}
TEST(InvokeTest, ReferenceWrapper) {
ConstFunctor cf;
MutableFunctor mf;
- EXPECT_EQ(1, Invoke(std::cref(cf), 3, 2));
- EXPECT_EQ(1, Invoke(std::ref(cf), 3, 2));
- EXPECT_EQ(1, Invoke(std::ref(mf), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
}
TEST(InvokeTest, MemberFunction) {
@@ -158,58 +168,62 @@ TEST(InvokeTest, MemberFunction) {
std::unique_ptr<const Class> cp(new Class);
std::unique_ptr<volatile Class> vp(new Class);
- EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::Method, *p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::RefMethod, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::RefMethod, p.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::RefMethod, *p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::RefRefMethod, std::move(*p), 3, 2)); // NOLINT
- EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, *p, 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, p.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, *p, 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, *cp, 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *vp, 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::Method, make_unique<Class>(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<Class>(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<const Class>(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
+ 2)); // NOLINT
+ EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
+
+ EXPECT_EQ(1,
+ base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
+ 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
+ make_unique<const Class>(), 3, 2));
}
TEST(InvokeTest, DataMember) {
std::unique_ptr<Class> p(new Class{42});
std::unique_ptr<const Class> cp(new Class{42});
- EXPECT_EQ(42, Invoke(&Class::member, p));
- EXPECT_EQ(42, Invoke(&Class::member, *p));
- EXPECT_EQ(42, Invoke(&Class::member, p.get()));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
- Invoke(&Class::member, p) = 42;
- Invoke(&Class::member, p.get()) = 42;
+ base_internal::invoke(&Class::member, p) = 42;
+ base_internal::invoke(&Class::member, p.get()) = 42;
- EXPECT_EQ(42, Invoke(&Class::member, cp));
- EXPECT_EQ(42, Invoke(&Class::member, *cp));
- EXPECT_EQ(42, Invoke(&Class::member, cp.get()));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
}
TEST(InvokeTest, FlipFlop) {
FlipFlop obj = {42};
// This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
// ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
- EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
- EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
+ EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
+ EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
}
TEST(InvokeTest, SfinaeFriendly) {
@@ -217,6 +231,100 @@ TEST(InvokeTest, SfinaeFriendly) {
EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
}
+TEST(IsInvocableRTest, CallableExactMatch) {
+ static_assert(
+ base_internal::is_invocable_r<int, decltype(Function), int, int>::value,
+ "Should be true for exact match of types on a free function");
+}
+
+TEST(IsInvocableRTest, CallableArgumentConversionMatch) {
+ static_assert(
+ base_internal::is_invocable_r<int, decltype(Function), char, int>::value,
+ "Should be true for convertible argument type");
+}
+
+TEST(IsInvocableRTest, CallableReturnConversionMatch) {
+ static_assert(base_internal::is_invocable_r<double, decltype(Function), int,
+ int>::value,
+ "Should be true for convertible return type");
+}
+
+TEST(IsInvocableRTest, CallableReturnVoid) {
+ static_assert(base_internal::is_invocable_r<void, decltype(VoidFunction),
+ int&, int&>::value,
+ "Should be true for void expected and actual return types");
+ static_assert(
+ base_internal::is_invocable_r<void, decltype(Function), int, int>::value,
+ "Should be true for void expected and non-void actual return types");
+}
+
+TEST(IsInvocableRTest, CallableRefQualifierMismatch) {
+ static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
+ int&, const int&>::value,
+ "Should be false for reference constness mismatch");
+ static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
+ int&&, int&>::value,
+ "Should be false for reference value category mismatch");
+}
+
+TEST(IsInvocableRTest, CallableArgumentTypeMismatch) {
+ static_assert(!base_internal::is_invocable_r<int, decltype(Function),
+ std::string, int>::value,
+ "Should be false for argument type mismatch");
+}
+
+TEST(IsInvocableRTest, CallableReturnTypeMismatch) {
+ static_assert(!base_internal::is_invocable_r<std::string, decltype(Function),
+ int, int>::value,
+ "Should be false for return type mismatch");
+}
+
+TEST(IsInvocableRTest, CallableTooFewArgs) {
+ static_assert(
+ !base_internal::is_invocable_r<int, decltype(Function), int>::value,
+ "Should be false for too few arguments");
+}
+
+TEST(IsInvocableRTest, CallableTooManyArgs) {
+ static_assert(!base_internal::is_invocable_r<int, decltype(Function), int,
+ int, int>::value,
+ "Should be false for too many arguments");
+}
+
+TEST(IsInvocableRTest, MemberFunctionAndReference) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
+ Class&, int, int>::value,
+ "Should be true for exact match of types on a member function "
+ "and class reference");
+}
+
+TEST(IsInvocableRTest, MemberFunctionAndPointer) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
+ Class*, int, int>::value,
+ "Should be true for exact match of types on a member function "
+ "and class pointer");
+}
+
+TEST(IsInvocableRTest, DataMemberAndReference) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
+ Class&>::value,
+ "Should be true for exact match of types on a data member and "
+ "class reference");
+}
+
+TEST(IsInvocableRTest, DataMemberAndPointer) {
+ static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
+ Class*>::value,
+ "Should be true for exact match of types on a data member and "
+ "class pointer");
+}
+
+TEST(IsInvocableRTest, CallableZeroArgs) {
+ static_assert(
+ base_internal::is_invocable_r<int, decltype(ZeroArgFunction)>::value,
+ "Should be true for exact match for a zero-arg free function");
+}
+
} // namespace
} // namespace base_internal
ABSL_NAMESPACE_END