Reduced template instantiation depth for the AllOf and AnyOf matchers. Also some formatting changes.
This commit is contained in:
@@ -384,12 +384,119 @@ inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
|
||||
return PolymorphicMatcher<Impl>(impl);
|
||||
}
|
||||
|
||||
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
|
||||
// and MUST NOT BE USED IN USER CODE!!!
|
||||
namespace internal {
|
||||
|
||||
// The MatcherCastImpl class template is a helper for implementing
|
||||
// MatcherCast(). We need this helper in order to partially
|
||||
// specialize the implementation of MatcherCast() (C++ allows
|
||||
// class/struct templates to be partially specialized, but not
|
||||
// function templates.).
|
||||
|
||||
// This general version is used when MatcherCast()'s argument is a
|
||||
// polymorphic matcher (i.e. something that can be converted to a
|
||||
// Matcher but is not one yet; for example, Eq(value)) or a value (for
|
||||
// example, "hello").
|
||||
template <typename T, typename M>
|
||||
class MatcherCastImpl {
|
||||
public:
|
||||
static Matcher<T> Cast(M polymorphic_matcher_or_value) {
|
||||
// M can be a polymorhic matcher, in which case we want to use
|
||||
// its conversion operator to create Matcher<T>. Or it can be a value
|
||||
// that should be passed to the Matcher<T>'s constructor.
|
||||
//
|
||||
// We can't call Matcher<T>(polymorphic_matcher_or_value) when M is a
|
||||
// polymorphic matcher because it'll be ambiguous if T has an implicit
|
||||
// constructor from M (this usually happens when T has an implicit
|
||||
// constructor from any type).
|
||||
//
|
||||
// It won't work to unconditionally implict_cast
|
||||
// polymorphic_matcher_or_value to Matcher<T> because it won't trigger
|
||||
// a user-defined conversion from M to T if one exists (assuming M is
|
||||
// a value).
|
||||
return CastImpl(
|
||||
polymorphic_matcher_or_value,
|
||||
BooleanConstant<
|
||||
internal::ImplicitlyConvertible<M, Matcher<T> >::value>());
|
||||
}
|
||||
|
||||
private:
|
||||
static Matcher<T> CastImpl(M value, BooleanConstant<false>) {
|
||||
// M can't be implicitly converted to Matcher<T>, so M isn't a polymorphic
|
||||
// matcher. It must be a value then. Use direct initialization to create
|
||||
// a matcher.
|
||||
return Matcher<T>(ImplicitCast_<T>(value));
|
||||
}
|
||||
|
||||
static Matcher<T> CastImpl(M polymorphic_matcher_or_value,
|
||||
BooleanConstant<true>) {
|
||||
// M is implicitly convertible to Matcher<T>, which means that either
|
||||
// M is a polymorhpic matcher or Matcher<T> has an implicit constructor
|
||||
// from M. In both cases using the implicit conversion will produce a
|
||||
// matcher.
|
||||
//
|
||||
// Even if T has an implicit constructor from M, it won't be called because
|
||||
// creating Matcher<T> would require a chain of two user-defined conversions
|
||||
// (first to create T from M and then to create Matcher<T> from T).
|
||||
return polymorphic_matcher_or_value;
|
||||
}
|
||||
};
|
||||
|
||||
// This more specialized version is used when MatcherCast()'s argument
|
||||
// is already a Matcher. This only compiles when type T can be
|
||||
// statically converted to type U.
|
||||
template <typename T, typename U>
|
||||
class MatcherCastImpl<T, Matcher<U> > {
|
||||
public:
|
||||
static Matcher<T> Cast(const Matcher<U>& source_matcher) {
|
||||
return Matcher<T>(new Impl(source_matcher));
|
||||
}
|
||||
|
||||
private:
|
||||
class Impl : public MatcherInterface<T> {
|
||||
public:
|
||||
explicit Impl(const Matcher<U>& source_matcher)
|
||||
: source_matcher_(source_matcher) {}
|
||||
|
||||
// We delegate the matching logic to the source matcher.
|
||||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
||||
return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
|
||||
}
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
source_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
source_matcher_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
private:
|
||||
const Matcher<U> source_matcher_;
|
||||
|
||||
GTEST_DISALLOW_ASSIGN_(Impl);
|
||||
};
|
||||
};
|
||||
|
||||
// This even more specialized version is used for efficiently casting
|
||||
// a matcher to its own type.
|
||||
template <typename T>
|
||||
class MatcherCastImpl<T, Matcher<T> > {
|
||||
public:
|
||||
static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// In order to be safe and clear, casting between different matcher
|
||||
// types is done explicitly via MatcherCast<T>(m), which takes a
|
||||
// matcher m and returns a Matcher<T>. It compiles only when T can be
|
||||
// statically converted to the argument type of m.
|
||||
template <typename T, typename M>
|
||||
Matcher<T> MatcherCast(M m);
|
||||
inline Matcher<T> MatcherCast(M matcher) {
|
||||
return internal::MatcherCastImpl<T, M>::Cast(matcher);
|
||||
}
|
||||
|
||||
// Implements SafeMatcherCast().
|
||||
//
|
||||
@@ -401,11 +508,11 @@ Matcher<T> MatcherCast(M m);
|
||||
template <typename T>
|
||||
class SafeMatcherCastImpl {
|
||||
public:
|
||||
// This overload handles polymorphic matchers only since monomorphic
|
||||
// matchers are handled by the next one.
|
||||
// This overload handles polymorphic matchers and values only since
|
||||
// monomorphic matchers are handled by the next one.
|
||||
template <typename M>
|
||||
static inline Matcher<T> Cast(M polymorphic_matcher) {
|
||||
return Matcher<T>(polymorphic_matcher);
|
||||
static inline Matcher<T> Cast(M polymorphic_matcher_or_value) {
|
||||
return internal::MatcherCastImpl<T, M>::Cast(polymorphic_matcher_or_value);
|
||||
}
|
||||
|
||||
// This overload handles monomorphic matchers.
|
||||
@@ -600,67 +707,6 @@ void ExplainMatchFailureTupleTo(const MatcherTuple& matchers,
|
||||
matchers, values, os);
|
||||
}
|
||||
|
||||
// The MatcherCastImpl class template is a helper for implementing
|
||||
// MatcherCast(). We need this helper in order to partially
|
||||
// specialize the implementation of MatcherCast() (C++ allows
|
||||
// class/struct templates to be partially specialized, but not
|
||||
// function templates.).
|
||||
|
||||
// This general version is used when MatcherCast()'s argument is a
|
||||
// polymorphic matcher (i.e. something that can be converted to a
|
||||
// Matcher but is not one yet; for example, Eq(value)).
|
||||
template <typename T, typename M>
|
||||
class MatcherCastImpl {
|
||||
public:
|
||||
static Matcher<T> Cast(M polymorphic_matcher) {
|
||||
return Matcher<T>(polymorphic_matcher);
|
||||
}
|
||||
};
|
||||
|
||||
// This more specialized version is used when MatcherCast()'s argument
|
||||
// is already a Matcher. This only compiles when type T can be
|
||||
// statically converted to type U.
|
||||
template <typename T, typename U>
|
||||
class MatcherCastImpl<T, Matcher<U> > {
|
||||
public:
|
||||
static Matcher<T> Cast(const Matcher<U>& source_matcher) {
|
||||
return Matcher<T>(new Impl(source_matcher));
|
||||
}
|
||||
|
||||
private:
|
||||
class Impl : public MatcherInterface<T> {
|
||||
public:
|
||||
explicit Impl(const Matcher<U>& source_matcher)
|
||||
: source_matcher_(source_matcher) {}
|
||||
|
||||
// We delegate the matching logic to the source matcher.
|
||||
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
|
||||
return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
|
||||
}
|
||||
|
||||
virtual void DescribeTo(::std::ostream* os) const {
|
||||
source_matcher_.DescribeTo(os);
|
||||
}
|
||||
|
||||
virtual void DescribeNegationTo(::std::ostream* os) const {
|
||||
source_matcher_.DescribeNegationTo(os);
|
||||
}
|
||||
|
||||
private:
|
||||
const Matcher<U> source_matcher_;
|
||||
|
||||
GTEST_DISALLOW_ASSIGN_(Impl);
|
||||
};
|
||||
};
|
||||
|
||||
// This even more specialized version is used for efficiently casting
|
||||
// a matcher to its own type.
|
||||
template <typename T>
|
||||
class MatcherCastImpl<T, Matcher<T> > {
|
||||
public:
|
||||
static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
|
||||
};
|
||||
|
||||
// Implements A<T>().
|
||||
template <typename T>
|
||||
class AnyMatcherImpl : public MatcherInterface<T> {
|
||||
@@ -1596,6 +1642,7 @@ class FloatingEqMatcher {
|
||||
operator Matcher<FloatType&>() const {
|
||||
return MakeMatcher(new Impl<FloatType&>(rhs_, nan_eq_nan_));
|
||||
}
|
||||
|
||||
private:
|
||||
const FloatType rhs_;
|
||||
const bool nan_eq_nan_;
|
||||
@@ -2633,12 +2680,6 @@ GTEST_API_ string FormatMatcherDescription(bool negation,
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// Implements MatcherCast().
|
||||
template <typename T, typename M>
|
||||
inline Matcher<T> MatcherCast(M matcher) {
|
||||
return internal::MatcherCastImpl<T, M>::Cast(matcher);
|
||||
}
|
||||
|
||||
// _ is a matcher that matches anything of any type.
|
||||
//
|
||||
// This definition is fine as:
|
||||
|
||||
Reference in New Issue
Block a user