summaryrefslogtreecommitdiffstats
path: root/googlemock/include
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2018-08-24 17:30:17 (GMT)
committerGennadiy Civil <misterg@google.com>2018-08-27 16:22:26 (GMT)
commita0e62d9f1a5f24cbc9d16bb9d1c4b606e960b2af (patch)
treee18a6c3959eef469e3199ff5bdca70a5b0316823 /googlemock/include
parent9c96f500a39df6915f8f1ab53b60be9889f1572b (diff)
downloadgoogletest-a0e62d9f1a5f24cbc9d16bb9d1c4b606e960b2af.zip
googletest-a0e62d9f1a5f24cbc9d16bb9d1c4b606e960b2af.tar.gz
googletest-a0e62d9f1a5f24cbc9d16bb9d1c4b606e960b2af.tar.bz2
No longer require a functor passed to ResultOf matcher to define `result_of` type.
This makes ResultOf more convenient to use. In particular, the matcher now accepts lambdas. PiperOrigin-RevId: 210118509
Diffstat (limited to 'googlemock/include')
-rw-r--r--googlemock/include/gmock/gmock-matchers.h69
1 files changed, 35 insertions, 34 deletions
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index 3336eff..3975cd0 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -2602,16 +2602,20 @@ class PropertyMatcher {
// Type traits specifying various features of different functors for ResultOf.
// The default template specifies features for functor objects.
-// Functor classes have to typedef argument_type and result_type
-// to be compatible with ResultOf.
template <typename Functor>
struct CallableTraits {
- typedef typename Functor::result_type ResultType;
typedef Functor StorageType;
static void CheckIsValid(Functor /* functor */) {}
+
+#if GTEST_LANG_CXX11
+ template <typename T>
+ static auto Invoke(Functor f, T arg) -> decltype(f(arg)) { return f(arg); }
+#else
+ typedef typename Functor::result_type ResultType;
template <typename T>
static ResultType Invoke(Functor f, T arg) { return f(arg); }
+#endif
};
// Specialization for function pointers.
@@ -2632,13 +2636,11 @@ struct CallableTraits<ResType(*)(ArgType)> {
// Implements the ResultOf() matcher for matching a return value of a
// unary function of an object.
-template <typename Callable>
+template <typename Callable, typename InnerMatcher>
class ResultOfMatcher {
public:
- typedef typename CallableTraits<Callable>::ResultType ResultType;
-
- ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher)
- : callable_(callable), matcher_(matcher) {
+ ResultOfMatcher(Callable callable, InnerMatcher matcher)
+ : callable_(internal::move(callable)), matcher_(internal::move(matcher)) {
CallableTraits<Callable>::CheckIsValid(callable_);
}
@@ -2652,9 +2654,17 @@ class ResultOfMatcher {
template <typename T>
class Impl : public MatcherInterface<T> {
+#if GTEST_LANG_CXX11
+ using ResultType = decltype(CallableTraits<Callable>::template Invoke<T>(
+ std::declval<CallableStorageType>(), std::declval<T>()));
+#else
+ typedef typename CallableTraits<Callable>::ResultType ResultType;
+#endif
+
public:
- Impl(CallableStorageType callable, const Matcher<ResultType>& matcher)
- : callable_(callable), matcher_(matcher) {}
+ template <typename M>
+ Impl(const CallableStorageType& callable, const M& matcher)
+ : callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {}
virtual void DescribeTo(::std::ostream* os) const {
*os << "is mapped by the given callable to a value that ";
@@ -2668,8 +2678,10 @@ class ResultOfMatcher {
virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
*listener << "which is mapped by the given callable to ";
- // Cannot pass the return value (for example, int) to
- // MatchPrintAndExplain, which takes a non-const reference as argument.
+ // Cannot pass the return value directly to MatchPrintAndExplain, which
+ // takes a non-const reference as argument.
+ // Also, specifying template argument explicitly is needed because T could
+ // be a non-const reference (e.g. Matcher<Uncopyable&>).
ResultType result =
CallableTraits<Callable>::template Invoke<T>(callable_, obj);
return MatchPrintAndExplain(result, matcher_, listener);
@@ -2679,7 +2691,7 @@ class ResultOfMatcher {
// Functors often define operator() as non-const method even though
// they are actually stateless. But we need to use them even when
// 'this' is a const pointer. It's the user's responsibility not to
- // use stateful callables with ResultOf(), which does't guarantee
+ // use stateful callables with ResultOf(), which doesn't guarantee
// how many times the callable will be invoked.
mutable CallableStorageType callable_;
const Matcher<ResultType> matcher_;
@@ -2688,7 +2700,7 @@ class ResultOfMatcher {
}; // class Impl
const CallableStorageType callable_;
- const Matcher<ResultType> matcher_;
+ const InnerMatcher matcher_;
GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
};
@@ -4554,26 +4566,15 @@ Property(const std::string& property_name,
// For example,
// ResultOf(f, StartsWith("hi"))
// matches a Foo object x iff f(x) starts with "hi".
-// callable parameter can be a function, function pointer, or a functor.
-// Callable has to satisfy the following conditions:
-// * It is required to keep no state affecting the results of
-// the calls on it and make no assumptions about how many calls
-// will be made. Any state it keeps must be protected from the
-// concurrent access.
-// * If it is a function object, it has to define type result_type.
-// We recommend deriving your functor classes from std::unary_function.
-//
-template <typename Callable, typename ResultOfMatcher>
-internal::ResultOfMatcher<Callable> ResultOf(
- Callable callable, const ResultOfMatcher& matcher) {
- return internal::ResultOfMatcher<Callable>(
- callable,
- MatcherCast<typename internal::CallableTraits<Callable>::ResultType>(
- matcher));
- // The call to MatcherCast() is required for supporting inner
- // matchers of compatible types. For example, it allows
- // ResultOf(Function, m)
- // to compile where Function() returns an int32 and m is a matcher for int64.
+// `callable` parameter can be a function, function pointer, or a functor. It is
+// required to keep no state affecting the results of the calls on it and make
+// no assumptions about how many calls will be made. Any state it keeps must be
+// protected from the concurrent access.
+template <typename Callable, typename InnerMatcher>
+internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
+ Callable callable, InnerMatcher matcher) {
+ return internal::ResultOfMatcher<Callable, InnerMatcher>(
+ internal::move(callable), internal::move(matcher));
}
// String matchers.