From d76486d885ccd337e7855d35c2418a8f936ef717 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 11 Apr 2026 16:53:55 -0700 Subject: [PATCH] [upstream_utils] Update googletest to HEAD (#8755) Co-authored-by: Tyler Veness --- .../googletest/include/gmock/gmock-actions.h | 238 +++-- .../include/gmock/gmock-cardinalities.h | 4 +- .../include/gmock/gmock-function-mocker.h | 9 +- .../googletest/include/gmock/gmock-matchers.h | 858 ++++++++++++------ .../include/gmock/gmock-more-actions.h | 23 +- .../include/gmock/gmock-more-matchers.h | 2 +- .../include/gmock/gmock-nice-strict.h | 18 +- .../include/gmock/gmock-spec-builders.h | 32 +- thirdparty/googletest/include/gmock/gmock.h | 15 +- .../gmock/internal/gmock-internal-utils.h | 57 +- .../include/gmock/internal/gmock-port.h | 15 +- .../include/gtest/gtest-assertion-result.h | 9 +- .../include/gtest/gtest-death-test.h | 12 +- .../googletest/include/gtest/gtest-matchers.h | 106 ++- .../googletest/include/gtest/gtest-message.h | 19 +- .../include/gtest/gtest-param-test.h | 136 ++- .../googletest/include/gtest/gtest-printers.h | 269 ++++-- .../googletest/include/gtest/gtest-spi.h | 4 +- .../include/gtest/gtest-test-part.h | 17 +- .../include/gtest/gtest-typed-test.h | 54 +- thirdparty/googletest/include/gtest/gtest.h | 124 ++- .../internal/gtest-death-test-internal.h | 73 +- .../include/gtest/internal/gtest-filepath.h | 10 +- .../include/gtest/internal/gtest-internal.h | 223 ++--- .../include/gtest/internal/gtest-param-util.h | 253 +++--- .../include/gtest/internal/gtest-port-arch.h | 4 + .../include/gtest/internal/gtest-port.h | 427 ++++----- .../include/gtest/internal/gtest-string.h | 4 +- .../include/gtest/internal/gtest-type-util.h | 6 +- .../googlemock/src/gmock-cardinalities.cpp | 8 +- .../googlemock/src/gmock-internal-utils.cpp | 9 +- .../src/googlemock/src/gmock-matchers.cpp | 29 +- .../googlemock/src/gmock-spec-builders.cpp | 35 +- .../src/googletest/src/gtest-death-test.cpp | 36 +- .../src/googletest/src/gtest-filepath.cpp | 2 +- .../src/googletest/src/gtest-internal-inl.h | 61 +- .../src/googletest/src/gtest-port.cpp | 133 ++- .../src/googletest/src/gtest-printers.cpp | 20 +- .../src/googletest/src/gtest-test-part.cpp | 8 +- .../googletest/src/googletest/src/gtest.cpp | 654 ++++++++----- upstream_utils/googletest.py | 3 +- 41 files changed, 2475 insertions(+), 1544 deletions(-) diff --git a/thirdparty/googletest/include/gmock/gmock-actions.h b/thirdparty/googletest/include/gmock/gmock-actions.h index bd9ba73ee6..94552cea21 100644 --- a/thirdparty/googletest/include/gmock/gmock-actions.h +++ b/thirdparty/googletest/include/gmock/gmock-actions.h @@ -135,6 +135,7 @@ #endif #include +#include #include #include #include @@ -175,9 +176,15 @@ struct BuiltInDefaultValueGetter { static T Get() { Assert(false, __FILE__, __LINE__, "Default action undefined for the function return type."); - return internal::Invalid(); +#if defined(__GNUC__) || defined(__clang__) + __builtin_unreachable(); +#elif defined(_MSC_VER) + __assume(0); +#else + return Invalid(); // The above statement will never be reached, but is required in // order for this function to compile. +#endif } }; @@ -189,7 +196,7 @@ struct BuiltInDefaultValueGetter { // other type T, the built-in default T value is undefined, and the // function will abort the process. template -class BuiltInDefaultValue { +class [[nodiscard]] BuiltInDefaultValue { public: // This function returns true if and only if type T has a built-in default // value. @@ -204,7 +211,7 @@ class BuiltInDefaultValue { // This partial specialization says that we use the same built-in // default value for T and const T. template -class BuiltInDefaultValue { +class [[nodiscard]] BuiltInDefaultValue { public: static bool Exists() { return BuiltInDefaultValue::Exists(); } static T Get() { return BuiltInDefaultValue::Get(); } @@ -213,7 +220,7 @@ class BuiltInDefaultValue { // This partial specialization defines the default values for pointer // types. template -class BuiltInDefaultValue { +class [[nodiscard]] BuiltInDefaultValue { public: static bool Exists() { return true; } static T* Get() { return nullptr; } @@ -376,7 +383,7 @@ typename std::add_const::type& as_const(T& t) { // Specialized for function types below. template -class OnceAction; +class [[nodiscard]] OnceAction; // An action that can only be used once. // @@ -414,7 +421,7 @@ class OnceAction; // A less-contrived example would be an action that returns an arbitrary type, // whose &&-qualified call operator is capable of dealing with move-only types. template -class OnceAction final { +class [[nodiscard]] OnceAction final { private: // True iff we can use the given callable type (or lvalue reference) directly // via StdFunctionAdaptor. @@ -567,7 +574,7 @@ class OnceAction final { // // Sets the default value for type T to be foo. // DefaultValue::Set(foo); template -class DefaultValue { +class [[nodiscard]] DefaultValue { public: // Sets the default value for type T; requires T to be // copy-constructable and have a public destructor. @@ -644,7 +651,7 @@ class DefaultValue { // This partial specialization allows a user to set default values for // reference types. template -class DefaultValue { +class [[nodiscard]] DefaultValue { public: // Sets the default value for type T&. static void Set(T& x) { // NOLINT @@ -678,7 +685,7 @@ class DefaultValue { // This specialization allows DefaultValue::Get() to // compile. template <> -class DefaultValue { +class [[nodiscard]] DefaultValue { public: static bool Exists() { return true; } static void Get() {} @@ -694,7 +701,7 @@ T* DefaultValue::address_ = nullptr; // Implement this interface to define an action for function type F. template -class ActionInterface { +class [[nodiscard]] ActionInterface { public: typedef typename internal::Function::Result Result; typedef typename internal::Function::ArgumentTuple ArgumentTuple; @@ -714,7 +721,7 @@ class ActionInterface { }; template -class Action; +class [[nodiscard]] Action; // An Action is a copyable and IMMUTABLE (except by assignment) // object that represents an action to be taken when a mock function of type @@ -723,7 +730,7 @@ class Action; // can view an object implementing ActionInterface as a concrete action // (including its current state), and an Action object as a handle to it. template -class Action { +class [[nodiscard]] Action { private: using F = R(Args...); @@ -828,6 +835,10 @@ class Action { Result operator()(const InArgs&...) const { return function_impl(); } + template + Result operator()(const InArgs&...) { + return function_impl(); + } FunctionImpl function_impl; }; @@ -858,7 +869,7 @@ class Action { // the definition of Return(void) and SetArgumentPointee(value) for // complete examples. template -class PolymorphicAction { +class [[nodiscard]] PolymorphicAction { public: explicit PolymorphicAction(const Impl& impl) : impl_(impl) {} @@ -918,7 +929,7 @@ struct ByMoveWrapper { // The general implementation of Return(R). Specializations follow below. template -class ReturnAction final { +class [[nodiscard]] ReturnAction final { public: explicit ReturnAction(R value) : value_(std::move(value)) {} @@ -1084,7 +1095,7 @@ class ReturnAction final { // the const call operator, checking at runtime that it isn't called more than // once, since the user has declared their intent to do so by using ByMove. template -class ReturnAction> final { +class [[nodiscard]] ReturnAction> final { public: explicit ReturnAction(ByMoveWrapper wrapper) : state_(new State(std::move(wrapper.payload))) {} @@ -1111,7 +1122,7 @@ class ReturnAction> final { }; // Implements the ReturnNull() action. -class ReturnNullAction { +class [[nodiscard]] ReturnNullAction { public: // Allows ReturnNull() to be used in any pointer-returning function. In C++11 // this is enforced by returning nullptr, and in non-C++11 by asserting a @@ -1123,7 +1134,7 @@ class ReturnNullAction { }; // Implements the Return() action. -class ReturnVoidAction { +class [[nodiscard]] ReturnVoidAction { public: // Allows Return() to be used in any void-returning function. template @@ -1136,7 +1147,7 @@ class ReturnVoidAction { // in any function that returns a reference to the type of x, // regardless of the argument types. template -class ReturnRefAction { +class [[nodiscard]] ReturnRefAction { public: // Constructs a ReturnRefAction object from the reference to be returned. explicit ReturnRefAction(T& ref) : ref_(ref) {} // NOLINT @@ -1177,7 +1188,7 @@ class ReturnRefAction { // used in any function that returns a reference to the type of x, // regardless of the argument types. template -class ReturnRefOfCopyAction { +class [[nodiscard]] ReturnRefOfCopyAction { public: // Constructs a ReturnRefOfCopyAction object from the reference to // be returned. @@ -1218,7 +1229,7 @@ class ReturnRefOfCopyAction { // Implements the polymorphic ReturnRoundRobin(v) action, which can be // used in any function that returns the element_type of v. template -class ReturnRoundRobinAction { +class [[nodiscard]] ReturnRoundRobinAction { public: explicit ReturnRoundRobinAction(std::vector values) { GTEST_CHECK_(!values.empty()) @@ -1246,7 +1257,7 @@ class ReturnRoundRobinAction { }; // Implements the polymorphic DoDefault() action. -class DoDefaultAction { +class [[nodiscard]] DoDefaultAction { public: // This template type conversion operator allows DoDefault() to be // used in any function. @@ -1259,7 +1270,7 @@ class DoDefaultAction { // Implements the Assign action to set a given pointer referent to a // particular value. template -class AssignAction { +class [[nodiscard]] AssignAction { public: AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {} @@ -1278,7 +1289,7 @@ class AssignAction { // Implements the SetErrnoAndReturn action to simulate return from // various system calls and libc functions. template -class SetErrnoAndReturnAction { +class [[nodiscard]] SetErrnoAndReturnAction { public: SetErrnoAndReturnAction(int errno_value, T result) : errno_(errno_value), result_(result) {} @@ -1386,7 +1397,7 @@ class IgnoreResultAction { void Perform(const ArgumentTuple& args) override { // Performs the action and ignores its result. - action_.Perform(args); + (void)action_.Perform(args); } private: @@ -1444,6 +1455,30 @@ struct WithArgsAction { return OA{std::move(inner_action)}; } + // As above, but in the case where we want to create a OnceAction from a const + // WithArgsAction. This is fine as long as the inner action doesn't need to + // move any of its state to create a OnceAction. + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>...)>>::value, + int>::type = 0> + operator OnceAction() const& { // NOLINT + struct OA { + OnceAction> inner_action; + + R operator()(Args&&... args) && { + return std::move(inner_action) + .Call(std::get( + std::forward_as_tuple(std::forward(args)...))...); + } + }; + + return OA{inner_action}; + } + template < typename R, typename... Args, typename std::enable_if< @@ -1468,11 +1503,11 @@ struct WithArgsAction { }; template -class DoAllAction; +class [[nodiscard]] DoAllAction; // Base case: only a single action. template -class DoAllAction { +class [[nodiscard]] DoAllAction { public: struct UserConstructorTag {}; @@ -1486,6 +1521,7 @@ class DoAllAction { // providing a call operator because even with a particular set of arguments // they don't have a fixed return type. + // We support conversion to OnceAction whenever the sub-action does. template >::value, @@ -1494,6 +1530,21 @@ class DoAllAction { return std::move(final_action_); } + // We also support conversion to OnceAction whenever the sub-action supports + // conversion to Action (since any Action can also be a OnceAction). + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + negation< + std::is_convertible>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return Action(std::move(final_action_)); + } + + // We support conversion to Action whenever the sub-action does. template < typename R, typename... Args, typename std::enable_if< @@ -1510,7 +1561,7 @@ class DoAllAction { // Recursive case: support N actions by calling the initial action and then // calling through to the base class containing N-1 actions. template -class DoAllAction +class [[nodiscard]] DoAllAction : private DoAllAction { private: using Base = DoAllAction; @@ -1573,16 +1624,16 @@ class DoAllAction : Base({}, std::forward(other_actions)...), initial_action_(std::forward(initial_action)) {} - template ...)>>, - std::is_convertible>>::value, - int>::type = 0> + // We support conversion to OnceAction whenever both the initial action and + // the rest support conversion to OnceAction. + template < + typename R, typename... Args, + typename std::enable_if< + conjunction...)>>, + std::is_convertible>>::value, + int>::type = 0> operator OnceAction() && { // NOLINT // Return an action that first calls the initial action with arguments // filtered through InitialActionArgType, then forwards arguments directly @@ -1605,12 +1656,34 @@ class DoAllAction }; } + // We also support conversion to OnceAction whenever the initial action + // supports conversion to Action (since any Action can also be a OnceAction). + // + // The remaining sub-actions must also be compatible, but we don't need to + // special case them because the base class deals with them. + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + negation...)>>>, + std::is_convertible...)>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return DoAll( + Action...)>(std::move(initial_action_)), + std::move(static_cast(*this))); + } + + // We support conversion to Action whenever both the initial action and the + // rest support conversion to Action. template < typename R, typename... Args, typename std::enable_if< conjunction< - // Both the initial action and the rest must support conversion to - // Action. std::is_convertible...)>>, std::is_convertible>>::value, @@ -1674,6 +1747,16 @@ struct SaveArgAction { } }; +template +struct SaveArgByMoveAction { + Ptr pointer; + + template + void operator()(Args&&... args) const { + *pointer = std::move(std::get(std::tie(args...))); + } +}; + template struct SaveArgPointeeAction { Ptr pointer; @@ -1713,11 +1796,24 @@ struct SetArrayArgumentAction { }; template -struct DeleteArgAction { +class [[nodiscard]] DeleteArgAction { + public: template void operator()(const Args&... args) const { - delete std::get(std::tie(args...)); + DoDelete(std::get(std::tie(args...))); } + + private: + template + static void DoDelete(T* ptr) { + delete ptr; + } + + template + [[deprecated( + "DeleteArg used for a non-pointer argument, it was likely migrated " + "to a smart pointer type. This action should be removed.")]] + static void DoDelete(T&) {} }; template @@ -1740,6 +1836,13 @@ struct ThrowAction { return [copy](Args...) -> R { throw copy; }; } }; +struct RethrowAction { + std::exception_ptr exception; + template + operator Action() const { // NOLINT + return [ex = exception](Args...) -> R { std::rethrow_exception(ex); }; + } +}; #endif // GTEST_HAS_EXCEPTIONS } // namespace internal @@ -1776,6 +1879,13 @@ struct ThrowAction { // EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin)); typedef internal::IgnoredValue Unused; +// Deprecated single-argument DoAll. +template +GTEST_INTERNAL_DEPRECATE_AND_INLINE("Avoid using DoAll() for single actions") +typename std::decay::type DoAll(Action&& action) { + return std::forward(action); +} + // Creates an action that does actions a1, a2, ..., sequentially in // each invocation. All but the last action will have a readonly view of the // arguments. @@ -1941,10 +2051,11 @@ PolymorphicAction> SetErrnoAndReturn( // Various overloads for Invoke(). // Legacy function. -// Actions can now be implicitly constructed from callables. No need to create -// wrapper objects. // This function exists for backwards compatibility. template +GTEST_INTERNAL_DEPRECATE_AND_INLINE( + "Actions can now be implicitly constructed from callables. No need to " + "create wrapper objects using Invoke().") typename std::decay::type Invoke(FunctionImpl&& function_impl) { return std::forward(function_impl); } @@ -2017,6 +2128,13 @@ internal::SaveArgAction SaveArg(Ptr pointer) { return {pointer}; } +// Action SaveArgByMove(pointer) moves the k-th (0-based) argument of the +// mock function into *pointer. +template +internal::SaveArgByMoveAction SaveArgByMove(Ptr pointer) { + return {pointer}; +} + // Action SaveArgPointee(pointer) saves the value pointed to // by the k-th (0-based) argument of the mock function to *pointer. template @@ -2056,13 +2174,23 @@ internal::ReturnPointeeAction ReturnPointee(Ptr pointer) { return {pointer}; } -// Action Throw(exception) can be used in a mock function of any type -// to throw the given exception. Any copyable value can be thrown. #if GTEST_HAS_EXCEPTIONS +// Action Throw(exception) can be used in a mock function of any type +// to throw the given exception. Any copyable value can be thrown, +// except for std::exception_ptr, which is likely a mistake if +// thrown directly. template -internal::ThrowAction::type> Throw(T&& exception) { +typename std::enable_if< + !std::is_base_of::type>::value, + internal::ThrowAction::type>>::type +Throw(T&& exception) { return {std::forward(exception)}; } +// Action Rethrow(exception_ptr) can be used in a mock function of any type +// to rethrow any exception_ptr. Note that the same object is thrown each time. +inline internal::RethrowAction Rethrow(std::exception_ptr exception) { + return {std::move(exception)}; +} #endif // GTEST_HAS_EXCEPTIONS namespace internal { @@ -2111,13 +2239,13 @@ struct ActionImpl : ImplBase::type { R operator()(Args&&... arg) const { static constexpr size_t kMaxArgs = sizeof...(Args) <= 10 ? sizeof...(Args) : 10; - return Apply(MakeIndexSequence{}, - MakeIndexSequence<10 - kMaxArgs>{}, + return Apply(std::make_index_sequence{}, + std::make_index_sequence<10 - kMaxArgs>{}, args_type{std::forward(arg)...}); } template - R Apply(IndexSequence, IndexSequence, + R Apply(std::index_sequence, std::index_sequence, const args_type& args) const { // Impl need not be specific to the signature of action being implemented; // only the implementing function body needs to have all of the specific @@ -2150,9 +2278,9 @@ template } #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ - , const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ - const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \ + , [[maybe_unused]] const arg##i##_type& arg##i +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ + [[maybe_unused]] const args_type& args GMOCK_PP_REPEAT( \ GMOCK_INTERNAL_ARG_UNUSED, , 10) #define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i @@ -2217,8 +2345,8 @@ template std::shared_ptr impl_; \ }; \ template \ - inline full_name name( \ - GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \ + [[nodiscard]] inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)); \ template \ inline full_name name( \ GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ @@ -2253,7 +2381,7 @@ template return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ }; \ }; \ - inline name##Action name() GTEST_MUST_USE_RESULT_; \ + [[nodiscard]] inline name##Action name(); \ inline name##Action name() { return name##Action(); } \ template \ diff --git a/thirdparty/googletest/include/gmock/gmock-cardinalities.h b/thirdparty/googletest/include/gmock/gmock-cardinalities.h index 533e604f32..c88c00c441 100644 --- a/thirdparty/googletest/include/gmock/gmock-cardinalities.h +++ b/thirdparty/googletest/include/gmock/gmock-cardinalities.h @@ -63,7 +63,7 @@ namespace testing { // management as Cardinality objects can now be copied like plain values. // The implementation of a cardinality. -class CardinalityInterface { +class [[nodiscard]] CardinalityInterface { public: virtual ~CardinalityInterface() = default; @@ -88,7 +88,7 @@ class CardinalityInterface { // object that specifies how many times a mock function is expected to // be called. The implementation of Cardinality is just a std::shared_ptr // to const CardinalityInterface. Don't inherit from Cardinality! -class GTEST_API_ Cardinality { +class GTEST_API_ [[nodiscard]] Cardinality { public: // Constructs a null cardinality. Needed for storing Cardinality // objects in STL containers. diff --git a/thirdparty/googletest/include/gmock/gmock-function-mocker.h b/thirdparty/googletest/include/gmock/gmock-function-mocker.h index 1a1f126e49..d2cb13cd83 100644 --- a/thirdparty/googletest/include/gmock/gmock-function-mocker.h +++ b/thirdparty/googletest/include/gmock/gmock-function-mocker.h @@ -37,6 +37,7 @@ #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ +#include #include // IWYU pragma: keep #include // IWYU pragma: keep @@ -69,22 +70,22 @@ constexpr bool PrefixOf(const char* a, const char* b) { return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1)); } -template +template constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) { return N <= M && internal::PrefixOf(prefix, str); } -template +template constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) { return N <= M && internal::PrefixOf(suffix, str + M - N); } -template +template constexpr bool Equals(const char (&a)[N], const char (&b)[M]) { return N == M && internal::PrefixOf(a, b); } -template +template constexpr bool ValidateSpec(const char (&spec)[N]) { return internal::Equals("const", spec) || internal::Equals("override", spec) || diff --git a/thirdparty/googletest/include/gmock/gmock-matchers.h b/thirdparty/googletest/include/gmock/gmock-matchers.h index 0f67713776..2f49371a6d 100644 --- a/thirdparty/googletest/include/gmock/gmock-matchers.h +++ b/thirdparty/googletest/include/gmock/gmock-matchers.h @@ -257,7 +257,7 @@ #include #include -#include +#include #include #include #include @@ -267,12 +267,12 @@ #include // NOLINT #include #include +#include #include #include #include #include "gmock/internal/gmock-internal-utils.h" -#include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-pp.h" #include "gtest/gtest.h" @@ -303,7 +303,7 @@ namespace testing { // plain values. // A match result listener that stores the explanation in a string. -class StringMatchResultListener : public MatchResultListener { +class [[nodiscard]] StringMatchResultListener : public MatchResultListener { public: StringMatchResultListener() : MatchResultListener(&ss_) {} @@ -336,7 +336,7 @@ namespace internal { // Matcher but is not one yet; for example, Eq(value)) or a value (for // example, "hello"). template -class MatcherCastImpl { +class [[nodiscard]] MatcherCastImpl { public: static Matcher Cast(const M& polymorphic_matcher_or_value) { // M can be a polymorphic matcher, in which case we want to use @@ -375,11 +375,16 @@ class MatcherCastImpl { // M can't be implicitly converted to Matcher, so M isn't a polymorphic // matcher. It's a value of a type implicitly convertible to T. Use direct - // initialization to create a matcher. + // initialization or `ImplicitCastEqMatcher` to create a matcher. static Matcher CastImpl(const M& value, std::false_type /* convertible_to_matcher */, std::true_type /* convertible_to_T */) { - return Matcher(ImplicitCast_(value)); + using NoRefT = std::remove_cv_t>; + if constexpr (std::is_same_v) { + return Matcher(value); + } else { + return ImplicitCastEqMatcher>(value); + } } // M can't be implicitly converted to either Matcher or T. Attempt to use @@ -390,31 +395,40 @@ class MatcherCastImpl { // latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end // which might be undefined even when Rhs is implicitly convertible to Lhs // (e.g. std::pair vs. std::pair). - // - // We don't define this method inline as we need the declaration of Eq(). static Matcher CastImpl(const M& value, std::false_type /* convertible_to_matcher */, - std::false_type /* convertible_to_T */); + std::false_type /* convertible_to_T */) { + return Eq(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 -class MatcherCastImpl> { +class [[nodiscard]] MatcherCastImpl> { public: static Matcher Cast(const Matcher& source_matcher) { return Matcher(new Impl(source_matcher)); } private: - class Impl : public MatcherInterface { + // If it's possible to implicitly convert a `const T&` to U, then `Impl` can + // take that as input to avoid a copy. Otherwise, such as when `T` is a + // non-const reference type or a type explicitly constructible only from a + // non-const reference, then `Impl` must use `T` as-is (potentially copying). + using ImplArgT = + typename std::conditional::value, + const T&, T>::type; + + class Impl : public MatcherInterface { public: explicit Impl(const Matcher& source_matcher) : source_matcher_(source_matcher) {} // We delegate the matching logic to the source matcher. - bool MatchAndExplain(T x, MatchResultListener* listener) const override { + bool MatchAndExplain(ImplArgT x, + MatchResultListener* listener) const override { using FromType = typename std::remove_cv::type>::type>::type; using ToType = typename std::remove_cv> { // Do the cast to `U` explicitly if necessary. // Otherwise, let implicit conversions do the trick. - using CastType = - typename std::conditional::value, - T&, U>::type; + using CastType = typename std::conditional< + std::is_convertible::value, ImplArgT&, U>::type; return source_matcher_.MatchAndExplain(static_cast(x), listener); @@ -455,14 +468,14 @@ class MatcherCastImpl> { // This even more specialized version is used for efficiently casting // a matcher to its own type. template -class MatcherCastImpl> { +class [[nodiscard]] MatcherCastImpl> { public: static Matcher Cast(const Matcher& matcher) { return matcher; } }; // Template specialization for parameterless Matcher. template -class MatcherBaseImpl { +class [[nodiscard]] MatcherBaseImpl { public: MatcherBaseImpl() = default; @@ -475,7 +488,7 @@ class MatcherBaseImpl { // Template specialization for Matcher with parameters. template