39 #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
40 #define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
46 #include <type_traits>
48 #include "gtest/gtest-printers.h"
49 #include "gtest/internal/gtest-internal.h"
50 #include "gtest/internal/gtest-port.h"
53 #if defined(_MSC_VER) && _MSC_VER >= 1915
54 #define GTEST_MAYBE_5046_ 5046
56 #define GTEST_MAYBE_5046_
77 class MatchResultListener {
115 virtual ~MatcherDescriberInterface() {}
122 virtual void DescribeTo(::std::ostream* os)
const = 0;
130 virtual void DescribeNegationTo(::std::ostream* os)
const {
138 template <
typename T>
139 class MatcherInterface :
public MatcherDescriberInterface {
182 template <
typename A,
typename B>
186 template <
typename A,
typename B>
190 template <
typename A,
typename B>
194 template <
typename A,
typename B>
198 template <
typename A,
typename B>
202 template <
typename A,
typename B>
207 class DummyMatchResultListener :
public MatchResultListener {
218 class StreamMatchResultListener :
public MatchResultListener {
227 struct SharedPayloadBase {
228 std::atomic<int>
ref{1};
229 void Ref() {
ref.fetch_add(1, std::memory_order_relaxed); }
230 bool Unref() {
return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; }
233 template <
typename T>
234 struct SharedPayload : SharedPayloadBase {
235 explicit SharedPayload(
const T&
v) :
value(
v) {}
238 static void Destroy(SharedPayloadBase* shared) {
239 delete static_cast<SharedPayload*
>(shared);
248 template <
typename T>
249 class MatcherBase :
private MatcherDescriberInterface {
255 return vtable_->match_and_explain(*
this,
x, listener);
260 DummyMatchResultListener
dummy;
265 void DescribeTo(::std::ostream* os)
const final {
267 vtable_->describe(*
this, os,
false);
273 vtable_->describe(*
this, os,
true);
278 StreamMatchResultListener listener(os);
286 if (vtable_ ==
nullptr)
return nullptr;
287 return vtable_->get_describer(*
this);
294 template <
typename U>
295 explicit MatcherBase(
const MatcherInterface<U>* impl) {
299 template <
typename M,
typename =
typename std::remove_reference<
300 M>::type::is_gtest_matcher>
302 Init(std::forward<M>(
m));
306 : vtable_(other.vtable_),
buffer_(other.buffer_) {
307 if (IsShared())
buffer_.shared->Ref();
311 if (
this == &other)
return *
this;
313 vtable_ = other.vtable_;
315 if (IsShared())
buffer_.shared->Ref();
320 : vtable_(other.vtable_),
buffer_(other.buffer_) {
321 other.vtable_ =
nullptr;
325 if (
this == &other)
return *
this;
327 vtable_ = other.vtable_;
329 other.vtable_ =
nullptr;
338 MatchResultListener*);
339 void (*describe)(
const MatcherBase&, std::ostream*,
bool negation);
342 const MatcherDescriberInterface* (*get_describer)(
const MatcherBase&);
344 void (*shared_destroy)(SharedPayloadBase*);
347 bool IsShared()
const {
348 return vtable_ !=
nullptr && vtable_->shared_destroy !=
nullptr;
352 template <
typename P>
354 MatchResultListener* listener)
356 return P::Get(
m).MatchAndExplain(
value, listener->stream());
359 template <
typename P>
361 MatchResultListener* listener)
366 template <
typename P>
367 static void DescribeImpl(
const MatcherBase&
m, std::ostream* os,
370 P::Get(
m).DescribeNegationTo(os);
376 template <
typename P>
377 static const MatcherDescriberInterface* GetDescriberImpl(
386 std::is_convertible<decltype(&
P::Get(
m)),
387 const MatcherDescriberInterface*>
::value
392 template <
typename P>
393 const VTable* GetVTable() {
394 static constexpr VTable kVTable = {&MatchAndExplainImpl<P>,
395 &DescribeImpl<P>, &GetDescriberImpl<P>,
406 SharedPayloadBase* shared;
410 if (IsShared() &&
buffer_.shared->Unref()) {
411 vtable_->shared_destroy(
buffer_.shared);
415 template <
typename M>
416 static constexpr
bool IsInlined() {
417 return sizeof(M) <=
sizeof(Buffer) &&
alignof(M) <=
alignof(Buffer) &&
422 template <typename M, bool = MatcherBase::IsInlined<M>()>
427 const M *
ptr =
static_cast<const M*
>(
428 static_cast<const void*
>(&
m.buffer_));
432 ::new (
static_cast<void*
>(&
m.buffer_)) M(impl);
434 static constexpr
auto shared_destroy =
nullptr;
437 template <
typename M>
438 struct ValuePolicy<M,
false> {
439 using Shared = SharedPayload<M>;
441 return static_cast<Shared*
>(
m.buffer_.shared)->
value;
443 template <
typename Arg>
445 m.buffer_.shared =
new Shared(std::forward<Arg>(
arg));
450 template <
typename U,
bool B>
451 struct ValuePolicy<
const MatcherInterface<U>*, B> {
452 using M =
const MatcherInterface<U>;
453 using Shared = SharedPayload<std::unique_ptr<M>>;
455 return *
static_cast<Shared*
>(
m.buffer_.shared)->
value;
458 m.buffer_.shared =
new Shared(std::unique_ptr<M>(impl));
464 template <
typename M>
467 using Policy = ValuePolicy<MM>;
468 vtable_ = GetVTable<Policy>();
472 const VTable* vtable_;
482 template <
typename T>
483 class Matcher :
public internal::MatcherBase<T> {
491 explicit Matcher(
const MatcherInterface<const T&>* impl)
492 : internal::MatcherBase<T>(impl) {}
494 template <
typename U>
496 const MatcherInterface<U>* impl,
499 : internal::MatcherBase<T>(impl) {}
501 template <
typename M,
typename =
typename std::remove_reference<
502 M>::type::is_gtest_matcher>
503 Matcher(M&&
m) : internal::MatcherBase<T>(std::forward<M>(
m)) {}
515 :
public internal::MatcherBase<const std::string&> {
519 explicit Matcher(
const MatcherInterface<const std::string&>* impl)
520 : internal::MatcherBase<const std::string&>(impl) {}
522 template <
typename M,
typename =
typename std::remove_reference<
523 M>::type::is_gtest_matcher>
525 : internal::MatcherBase<const std::string&>(std::forward<M>(
m)) {}
532 Matcher(
const char* s);
537 :
public internal::MatcherBase<std::string> {
541 explicit Matcher(
const MatcherInterface<const std::string&>* impl)
542 : internal::MatcherBase<std::string>(impl) {}
543 explicit Matcher(
const MatcherInterface<std::string>* impl)
544 : internal::MatcherBase<std::string>(impl) {}
546 template <
typename M,
typename =
typename std::remove_reference<
547 M>::type::is_gtest_matcher>
549 : internal::MatcherBase<std::string>(std::forward<M>(
m)) {}
556 Matcher(
const char* s);
559 #if GTEST_INTERNAL_HAS_STRING_VIEW
565 :
public internal::MatcherBase<const internal::StringView&> {
569 explicit Matcher(
const MatcherInterface<const internal::StringView&>* impl)
570 : internal::MatcherBase<const internal::StringView&>(impl) {}
572 template <
typename M,
typename =
typename std::remove_reference<
573 M>::type::is_gtest_matcher>
575 : internal::MatcherBase<const internal::StringView&>(std::forward<M>(
m)) {
583 Matcher(
const char* s);
586 Matcher(internal::StringView s);
591 :
public internal::MatcherBase<internal::StringView> {
595 explicit Matcher(
const MatcherInterface<const internal::StringView&>* impl)
596 : internal::MatcherBase<internal::StringView>(impl) {}
597 explicit Matcher(
const MatcherInterface<internal::StringView>* impl)
598 : internal::MatcherBase<internal::StringView>(impl) {}
600 template <
typename M,
typename =
typename std::remove_reference<
601 M>::type::is_gtest_matcher>
603 : internal::MatcherBase<internal::StringView>(std::forward<M>(
m)) {}
610 Matcher(
const char* s);
613 Matcher(internal::StringView s);
615 #endif // GTEST_INTERNAL_HAS_STRING_VIEW
618 template <
typename T>
619 std::ostream&
operator<<(std::ostream& os,
const Matcher<T>& matcher) {
620 matcher.DescribeTo(&os);
636 template <
class Impl>
637 class PolymorphicMatcher {
647 const Impl&
impl()
const {
return impl_; }
649 template <
typename T>
650 operator Matcher<T>()
const {
651 return Matcher<T>(
new MonomorphicImpl<const T&>(
impl_));
655 template <
typename T>
656 class MonomorphicImpl :
public MatcherInterface<T> {
660 void DescribeTo(::std::ostream* os)
const override {
impl_.DescribeTo(os); }
663 impl_.DescribeNegationTo(os);
667 return impl_.MatchAndExplain(
x, listener);
683 template <
typename T>
684 inline Matcher<T>
MakeMatcher(
const MatcherInterface<T>* impl) {
685 return Matcher<T>(impl);
695 template <
class Impl>
697 return PolymorphicMatcher<Impl>(impl);
711 template <
typename D,
typename Rhs,
typename Op>
712 class ComparisonBase {
716 using is_gtest_matcher = void;
718 template <
typename Lhs>
719 bool MatchAndExplain(
const Lhs& lhs, std::ostream*)
const {
720 return Op()(lhs, Unwrap(
rhs_));
722 void DescribeTo(std::ostream* os)
const {
723 *os << D::Desc() <<
" ";
726 void DescribeNegationTo(std::ostream* os)
const {
727 *os << D::NegatedDesc() <<
" ";
732 template <
typename T>
733 static const T& Unwrap(
const T&
v) {
736 template <
typename T>
737 static const T& Unwrap(std::reference_wrapper<T>
v) {
744 template <
typename Rhs>
745 class EqMatcher :
public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
748 : ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
749 static const char*
Desc() {
return "is equal to"; }
750 static const char*
NegatedDesc() {
return "isn't equal to"; }
752 template <
typename Rhs>
753 class NeMatcher :
public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
756 : ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
757 static const char*
Desc() {
return "isn't equal to"; }
758 static const char*
NegatedDesc() {
return "is equal to"; }
760 template <
typename Rhs>
761 class LtMatcher :
public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
764 : ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
765 static const char*
Desc() {
return "is <"; }
766 static const char*
NegatedDesc() {
return "isn't <"; }
768 template <
typename Rhs>
769 class GtMatcher :
public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
772 : ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
773 static const char*
Desc() {
return "is >"; }
774 static const char*
NegatedDesc() {
return "isn't >"; }
776 template <
typename Rhs>
777 class LeMatcher :
public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
780 : ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
781 static const char*
Desc() {
return "is <="; }
782 static const char*
NegatedDesc() {
return "isn't <="; }
784 template <
typename Rhs>
785 class GeMatcher :
public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
788 : ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
789 static const char*
Desc() {
return "is >="; }
790 static const char*
NegatedDesc() {
return "isn't >="; }
793 template <
typename T,
typename =
typename std::enable_if<
795 using StringLike =
T;
800 class MatchesRegexMatcher {
805 #if GTEST_INTERNAL_HAS_STRING_VIEW
807 MatchResultListener* listener)
const {
810 #endif // GTEST_INTERNAL_HAS_STRING_VIEW
817 template <
typename CharType>
818 bool MatchAndExplain(CharType* s, MatchResultListener* listener)
const {
826 template <
class MatcheeStringType>
828 MatchResultListener* )
const {
835 *os << (
full_match_ ?
"matches" :
"contains") <<
" regular expression ";
840 *os <<
"doesn't " << (
full_match_ ?
"match" :
"contain")
841 <<
" regular expression ";
846 const std::shared_ptr<const RE>
regex_;
853 inline PolymorphicMatcher<internal::MatchesRegexMatcher>
MatchesRegex(
854 const internal::RE* regex) {
857 template <
typename T = std::
string>
858 PolymorphicMatcher<internal::MatchesRegexMatcher>
MatchesRegex(
859 const internal::StringLike<T>& regex) {
865 inline PolymorphicMatcher<internal::MatchesRegexMatcher>
ContainsRegex(
866 const internal::RE* regex) {
869 template <
typename T = std::
string>
870 PolymorphicMatcher<internal::MatchesRegexMatcher>
ContainsRegex(
871 const internal::StringLike<T>& regex) {
878 template <
typename T>
879 inline internal::EqMatcher<T>
Eq(
T x) {
return internal::EqMatcher<T>(
x); }
883 template <
typename T>
898 template <
typename Lhs,
typename Rhs>
899 inline Matcher<Lhs>
TypedEq(
const Rhs& rhs) {
return Eq(rhs); }
902 template <
typename Rhs>
903 inline internal::GeMatcher<Rhs>
Ge(Rhs
x) {
904 return internal::GeMatcher<Rhs>(
x);
908 template <
typename Rhs>
909 inline internal::GtMatcher<Rhs>
Gt(Rhs
x) {
910 return internal::GtMatcher<Rhs>(
x);
914 template <
typename Rhs>
915 inline internal::LeMatcher<Rhs>
Le(Rhs
x) {
916 return internal::LeMatcher<Rhs>(
x);
920 template <
typename Rhs>
921 inline internal::LtMatcher<Rhs>
Lt(Rhs
x) {
922 return internal::LtMatcher<Rhs>(
x);
926 template <
typename Rhs>
927 inline internal::NeMatcher<Rhs>
Ne(Rhs
x) {
928 return internal::NeMatcher<Rhs>(
x);
934 #endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_