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
This commit is contained in:
		
							parent
							
								
									e3e76f3b9f
								
							
						
					
					
						commit
						b8dfc2efee
					
				@ -2602,16 +2602,20 @@ class PropertyMatcher {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Type traits specifying various features of different functors for ResultOf.
 | 
					// Type traits specifying various features of different functors for ResultOf.
 | 
				
			||||||
// The default template specifies features for functor objects.
 | 
					// 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>
 | 
					template <typename Functor>
 | 
				
			||||||
struct CallableTraits {
 | 
					struct CallableTraits {
 | 
				
			||||||
  typedef typename Functor::result_type ResultType;
 | 
					 | 
				
			||||||
  typedef Functor StorageType;
 | 
					  typedef Functor StorageType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static void CheckIsValid(Functor /* functor */) {}
 | 
					  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>
 | 
					  template <typename T>
 | 
				
			||||||
  static ResultType Invoke(Functor f, T arg) { return f(arg); }
 | 
					  static ResultType Invoke(Functor f, T arg) { return f(arg); }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Specialization for function pointers.
 | 
					// Specialization for function pointers.
 | 
				
			||||||
@ -2632,13 +2636,11 @@ struct CallableTraits<ResType(*)(ArgType)> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Implements the ResultOf() matcher for matching a return value of a
 | 
					// Implements the ResultOf() matcher for matching a return value of a
 | 
				
			||||||
// unary function of an object.
 | 
					// unary function of an object.
 | 
				
			||||||
template <typename Callable>
 | 
					template <typename Callable, typename InnerMatcher>
 | 
				
			||||||
class ResultOfMatcher {
 | 
					class ResultOfMatcher {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  typedef typename CallableTraits<Callable>::ResultType ResultType;
 | 
					  ResultOfMatcher(Callable callable, InnerMatcher matcher)
 | 
				
			||||||
 | 
					      : callable_(internal::move(callable)), matcher_(internal::move(matcher)) {
 | 
				
			||||||
  ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher)
 | 
					 | 
				
			||||||
      : callable_(callable), matcher_(matcher) {
 | 
					 | 
				
			||||||
    CallableTraits<Callable>::CheckIsValid(callable_);
 | 
					    CallableTraits<Callable>::CheckIsValid(callable_);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2652,9 +2654,17 @@ class ResultOfMatcher {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  template <typename T>
 | 
					  template <typename T>
 | 
				
			||||||
  class Impl : public MatcherInterface<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:
 | 
					   public:
 | 
				
			||||||
    Impl(CallableStorageType callable, const Matcher<ResultType>& matcher)
 | 
					    template <typename M>
 | 
				
			||||||
        : callable_(callable), matcher_(matcher) {}
 | 
					    Impl(const CallableStorageType& callable, const M& matcher)
 | 
				
			||||||
 | 
					        : callable_(callable), matcher_(MatcherCast<ResultType>(matcher)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual void DescribeTo(::std::ostream* os) const {
 | 
					    virtual void DescribeTo(::std::ostream* os) const {
 | 
				
			||||||
      *os << "is mapped by the given callable to a value that ";
 | 
					      *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 {
 | 
					    virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
 | 
				
			||||||
      *listener << "which is mapped by the given callable to ";
 | 
					      *listener << "which is mapped by the given callable to ";
 | 
				
			||||||
      // Cannot pass the return value (for example, int) to
 | 
					      // Cannot pass the return value directly to MatchPrintAndExplain, which
 | 
				
			||||||
      // MatchPrintAndExplain, which takes a non-const reference as argument.
 | 
					      // 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 =
 | 
					      ResultType result =
 | 
				
			||||||
          CallableTraits<Callable>::template Invoke<T>(callable_, obj);
 | 
					          CallableTraits<Callable>::template Invoke<T>(callable_, obj);
 | 
				
			||||||
      return MatchPrintAndExplain(result, matcher_, listener);
 | 
					      return MatchPrintAndExplain(result, matcher_, listener);
 | 
				
			||||||
@ -2679,7 +2691,7 @@ class ResultOfMatcher {
 | 
				
			|||||||
    // Functors often define operator() as non-const method even though
 | 
					    // Functors often define operator() as non-const method even though
 | 
				
			||||||
    // they are actually stateless. But we need to use them even when
 | 
					    // 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
 | 
					    // '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.
 | 
					    // how many times the callable will be invoked.
 | 
				
			||||||
    mutable CallableStorageType callable_;
 | 
					    mutable CallableStorageType callable_;
 | 
				
			||||||
    const Matcher<ResultType> matcher_;
 | 
					    const Matcher<ResultType> matcher_;
 | 
				
			||||||
@ -2688,7 +2700,7 @@ class ResultOfMatcher {
 | 
				
			|||||||
  };  // class Impl
 | 
					  };  // class Impl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const CallableStorageType callable_;
 | 
					  const CallableStorageType callable_;
 | 
				
			||||||
  const Matcher<ResultType> matcher_;
 | 
					  const InnerMatcher matcher_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
 | 
					  GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -4554,26 +4566,15 @@ Property(const std::string& property_name,
 | 
				
			|||||||
// For example,
 | 
					// For example,
 | 
				
			||||||
//   ResultOf(f, StartsWith("hi"))
 | 
					//   ResultOf(f, StartsWith("hi"))
 | 
				
			||||||
// matches a Foo object x iff f(x) starts with "hi".
 | 
					// matches a Foo object x iff f(x) starts with "hi".
 | 
				
			||||||
// callable parameter can be a function, function pointer, or a functor.
 | 
					// `callable` parameter can be a function, function pointer, or a functor. It is
 | 
				
			||||||
// Callable has to satisfy the following conditions:
 | 
					// required to keep no state affecting the results of the calls on it and make
 | 
				
			||||||
//   * It is required to keep no state affecting the results of
 | 
					// no assumptions about how many calls will be made. Any state it keeps must be
 | 
				
			||||||
//     the calls on it and make no assumptions about how many calls
 | 
					// protected from the concurrent access.
 | 
				
			||||||
//     will be made. Any state it keeps must be protected from the
 | 
					template <typename Callable, typename InnerMatcher>
 | 
				
			||||||
//     concurrent access.
 | 
					internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf(
 | 
				
			||||||
//   * If it is a function object, it has to define type result_type.
 | 
					    Callable callable, InnerMatcher matcher) {
 | 
				
			||||||
//     We recommend deriving your functor classes from std::unary_function.
 | 
					  return internal::ResultOfMatcher<Callable, InnerMatcher>(
 | 
				
			||||||
//
 | 
					      internal::move(callable), internal::move(matcher));
 | 
				
			||||||
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.
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// String matchers.
 | 
					// String matchers.
 | 
				
			||||||
 | 
				
			|||||||
@ -4597,6 +4597,7 @@ struct PolymorphicFunctor {
 | 
				
			|||||||
  typedef int result_type;
 | 
					  typedef int result_type;
 | 
				
			||||||
  int operator()(int n) { return n; }
 | 
					  int operator()(int n) { return n; }
 | 
				
			||||||
  int operator()(const char* s) { return static_cast<int>(strlen(s)); }
 | 
					  int operator()(const char* s) { return static_cast<int>(strlen(s)); }
 | 
				
			||||||
 | 
					  std::string operator()(int *p) { return p ? "good ptr" : "null"; }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST(ResultOfTest, WorksForPolymorphicFunctors) {
 | 
					TEST(ResultOfTest, WorksForPolymorphicFunctors) {
 | 
				
			||||||
@ -4611,6 +4612,23 @@ TEST(ResultOfTest, WorksForPolymorphicFunctors) {
 | 
				
			|||||||
  EXPECT_FALSE(matcher_string.Matches("shrt"));
 | 
					  EXPECT_FALSE(matcher_string.Matches("shrt"));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if GTEST_LANG_CXX11
 | 
				
			||||||
 | 
					TEST(ResultOfTest, WorksForPolymorphicFunctorsIgnoringResultType) {
 | 
				
			||||||
 | 
					  Matcher<int*> matcher = ResultOf(PolymorphicFunctor(), "good ptr");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int n = 0;
 | 
				
			||||||
 | 
					  EXPECT_TRUE(matcher.Matches(&n));
 | 
				
			||||||
 | 
					  EXPECT_FALSE(matcher.Matches(nullptr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(ResultOfTest, WorksForLambdas) {
 | 
				
			||||||
 | 
					  Matcher<int> matcher =
 | 
				
			||||||
 | 
					      ResultOf([](int str_len) { return std::string(str_len, 'x'); }, "xxx");
 | 
				
			||||||
 | 
					  EXPECT_TRUE(matcher.Matches(3));
 | 
				
			||||||
 | 
					  EXPECT_FALSE(matcher.Matches(1));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const int* ReferencingFunction(const int& n) { return &n; }
 | 
					const int* ReferencingFunction(const int& n) { return &n; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ReferencingFunctor {
 | 
					struct ReferencingFunctor {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user