Googletest export
Change Matcher<T> to allow binding an implementation by value directly: - Drop the requirement of MatcherInterface. Doing manual type erasure avoid extra layers in many cases. - Avoid the adaptor for `MatcherInterface<T>` and `MatcherInterface<const T&>` mismatch. - Use a small object optimization when possible. This makes things like `_` and `Eq(1)` really cheap and do not require memory allocations. - Migrate some matchers to the new model to speed them up and to test the new framework. More matchers to come in future changes. PiperOrigin-RevId: 350580998
This commit is contained in:
@@ -735,31 +735,25 @@ OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) {
|
||||
return TransformTupleValuesHelper<Tuple, Func, OutIter>::Run(f, t, out);
|
||||
}
|
||||
|
||||
// Implements A<T>().
|
||||
template <typename T>
|
||||
class AnyMatcherImpl : public MatcherInterface<const T&> {
|
||||
public:
|
||||
bool MatchAndExplain(const T& /* x */,
|
||||
MatchResultListener* /* listener */) const override {
|
||||
return true;
|
||||
}
|
||||
void DescribeTo(::std::ostream* os) const override { *os << "is anything"; }
|
||||
void DescribeNegationTo(::std::ostream* os) const override {
|
||||
// This is mostly for completeness' safe, as it's not very useful
|
||||
// to write Not(A<bool>()). However we cannot completely rule out
|
||||
// such a possibility, and it doesn't hurt to be prepared.
|
||||
*os << "never matches";
|
||||
}
|
||||
};
|
||||
|
||||
// Implements _, a matcher that matches any value of any
|
||||
// type. This is a polymorphic matcher, so we need a template type
|
||||
// conversion operator to make it appearing as a Matcher<T> for any
|
||||
// type T.
|
||||
class AnythingMatcher {
|
||||
public:
|
||||
using is_gtest_matcher = void;
|
||||
|
||||
template <typename T>
|
||||
operator Matcher<T>() const { return A<T>(); }
|
||||
bool MatchAndExplain(const T& /* x */, std::ostream* /* listener */) const {
|
||||
return true;
|
||||
}
|
||||
void DescribeTo(std::ostream* os) const { *os << "is anything"; }
|
||||
void DescribeNegationTo(::std::ostream* os) const {
|
||||
// This is mostly for completeness' sake, as it's not very useful
|
||||
// to write Not(A<bool>()). However we cannot completely rule out
|
||||
// such a possibility, and it doesn't hurt to be prepared.
|
||||
*os << "never matches";
|
||||
}
|
||||
};
|
||||
|
||||
// Implements the polymorphic IsNull() matcher, which matches any raw or smart
|
||||
@@ -3443,7 +3437,9 @@ class UnorderedElementsAreMatcherImpl
|
||||
: UnorderedElementsAreMatcherImplBase(matcher_flags) {
|
||||
for (; first != last; ++first) {
|
||||
matchers_.push_back(MatcherCast<const Element&>(*first));
|
||||
matcher_describers().push_back(matchers_.back().GetDescriber());
|
||||
}
|
||||
for (const auto& m : matchers_) {
|
||||
matcher_describers().push_back(m.GetDescriber());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4068,12 +4064,14 @@ const internal::AnythingMatcher _ = {};
|
||||
// Creates a matcher that matches any value of the given type T.
|
||||
template <typename T>
|
||||
inline Matcher<T> A() {
|
||||
return Matcher<T>(new internal::AnyMatcherImpl<T>());
|
||||
return _;
|
||||
}
|
||||
|
||||
// Creates a matcher that matches any value of the given type T.
|
||||
template <typename T>
|
||||
inline Matcher<T> An() { return A<T>(); }
|
||||
inline Matcher<T> An() {
|
||||
return _;
|
||||
}
|
||||
|
||||
template <typename T, typename M>
|
||||
Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl(
|
||||
|
||||
@@ -410,7 +410,7 @@ TEST(StringMatcherTest,
|
||||
// MatcherInterface* without requiring the user to explicitly
|
||||
// write the type.
|
||||
TEST(MakeMatcherTest, ConstructsMatcherFromMatcherInterface) {
|
||||
const MatcherInterface<int>* dummy_impl = nullptr;
|
||||
const MatcherInterface<int>* dummy_impl = new EvenMatcherImpl;
|
||||
Matcher<int> m = MakeMatcher(dummy_impl);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user