diff --git a/include/gmock/gmock-matchers.h b/include/gmock/gmock-matchers.h index b92450ca..c21fa515 100644 --- a/include/gmock/gmock-matchers.h +++ b/include/gmock/gmock-matchers.h @@ -1392,15 +1392,15 @@ class TrulyMatcher { template bool MatchAndExplain(T& x, // NOLINT MatchResultListener* /* listener */) const { -#ifdef _MSC_VER - // MSVC warns about converting a value into bool (warning 4800). -# pragma warning(push) // Saves the current warning state. -# pragma warning(disable:4800) // Temporarily disables warning 4800. -#endif - return predicate_(x); -#ifdef _MSC_VER -# pragma warning(pop) // Restores the warning state. -#endif + // Without the if-statement, MSVC sometimes warns about converting + // a value to bool (warning 4800). + // + // We cannot write 'return !!predicate_(x);' as that doesn't work + // when predicate_(x) returns a class convertible to bool but + // having no operator!(). + if (predicate_(x)) + return true; + return false; } void DescribeTo(::std::ostream* os) const { diff --git a/test/gmock-matchers_test.cc b/test/gmock-matchers_test.cc index 6f93fbd7..9ad62c47 100644 --- a/test/gmock-matchers_test.cc +++ b/test/gmock-matchers_test.cc @@ -2256,6 +2256,29 @@ TEST(TrulyTest, CanBeUsedWithFunctor) { EXPECT_FALSE(m.Matches(4)); } +// A class that can be implicitly converted to bool. +class ConvertibleToBool { + public: + explicit ConvertibleToBool(int number) : number_(number) {} + operator bool() const { return number_ != 0; } + + private: + int number_; +}; + +ConvertibleToBool IsNotZero(int number) { + return ConvertibleToBool(number); +} + +// Tests that the predicate used in Truly() may return a class that's +// implicitly convertible to bool, even when the class has no +// operator!(). +TEST(TrulyTest, PredicateCanReturnAClassConvertibleToBool) { + Matcher m = Truly(IsNotZero); + EXPECT_TRUE(m.Matches(1)); + EXPECT_FALSE(m.Matches(0)); +} + // Tests that Truly(predicate) can describe itself properly. TEST(TrulyTest, CanDescribeSelf) { Matcher m = Truly(IsPositive);