Googletest export
Simplify the fallback printing logic to have a single sequence of trial printers. PiperOrigin-RevId: 298621376
This commit is contained in:
		@@ -119,106 +119,91 @@
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
 | 
			
		||||
// Definitions in the 'internal' and 'internal2' name spaces are
 | 
			
		||||
// subject to change without notice.  DO NOT USE THEM IN USER CODE!
 | 
			
		||||
namespace internal2 {
 | 
			
		||||
 | 
			
		||||
// Prints the given number of bytes in the given object to the given
 | 
			
		||||
// ostream.
 | 
			
		||||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
 | 
			
		||||
                                     size_t count,
 | 
			
		||||
                                     ::std::ostream* os);
 | 
			
		||||
 | 
			
		||||
// For selecting which printer to use when a given type has neither <<
 | 
			
		||||
// nor PrintTo().
 | 
			
		||||
enum TypeKind {
 | 
			
		||||
  kProtobuf,              // a protobuf type
 | 
			
		||||
  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
 | 
			
		||||
                          // (e.g. a named or unnamed enum type)
 | 
			
		||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
 | 
			
		||||
  kConvertibleToStringView,  // a type implicitly convertible to
 | 
			
		||||
                             // absl::string_view or std::string_view
 | 
			
		||||
#endif
 | 
			
		||||
  kOtherType  // anything else
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
 | 
			
		||||
// by the universal printer to print a value of type T when neither
 | 
			
		||||
// operator<< nor PrintTo() is defined for T, where kTypeKind is the
 | 
			
		||||
// "kind" of T as defined by enum TypeKind.
 | 
			
		||||
template <typename T, TypeKind kTypeKind>
 | 
			
		||||
class TypeWithoutFormatter {
 | 
			
		||||
 public:
 | 
			
		||||
  // This default version is called when kTypeKind is kOtherType.
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os) {
 | 
			
		||||
    PrintBytesInObjectTo(
 | 
			
		||||
        static_cast<const unsigned char*>(
 | 
			
		||||
            reinterpret_cast<const void*>(std::addressof(value))),
 | 
			
		||||
        sizeof(value), os);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// We print a protobuf using its ShortDebugString() when the string
 | 
			
		||||
// doesn't exceed this many characters; otherwise we print it using
 | 
			
		||||
// DebugString() for better readability.
 | 
			
		||||
const size_t kProtobufOneLinerMaxLength = 50;
 | 
			
		||||
// Definitions in the internal* namespaces are subject to change without notice.
 | 
			
		||||
// DO NOT USE THEM IN USER CODE!
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
class TypeWithoutFormatter<T, kProtobuf> {
 | 
			
		||||
 public:
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os) {
 | 
			
		||||
    std::string pretty_str = value.ShortDebugString();
 | 
			
		||||
    if (pretty_str.length() > kProtobufOneLinerMaxLength) {
 | 
			
		||||
      pretty_str = "\n" + value.DebugString();
 | 
			
		||||
void UniversalPrint(const T& value, ::std::ostream* os);
 | 
			
		||||
 | 
			
		||||
// Used to print an STL-style container when the user doesn't define
 | 
			
		||||
// a PrintTo() for it.
 | 
			
		||||
struct ContainerPrinter {
 | 
			
		||||
  template <typename T,
 | 
			
		||||
            typename = typename std::enable_if<
 | 
			
		||||
                (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
 | 
			
		||||
                !IsRecursiveContainer<T>::value>::type>
 | 
			
		||||
  static void PrintValue(const T& container, std::ostream* os) {
 | 
			
		||||
    const size_t kMaxCount = 32;  // The maximum number of elements to print.
 | 
			
		||||
    *os << '{';
 | 
			
		||||
    size_t count = 0;
 | 
			
		||||
    for (auto&& elem : container) {
 | 
			
		||||
      if (count > 0) {
 | 
			
		||||
        *os << ',';
 | 
			
		||||
        if (count == kMaxCount) {  // Enough has been printed.
 | 
			
		||||
          *os << " ...";
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      *os << ' ';
 | 
			
		||||
      // We cannot call PrintTo(elem, os) here as PrintTo() doesn't
 | 
			
		||||
      // handle `elem` being a native array.
 | 
			
		||||
      internal::UniversalPrint(elem, os);
 | 
			
		||||
      ++count;
 | 
			
		||||
    }
 | 
			
		||||
    *os << ("<" + pretty_str + ">");
 | 
			
		||||
 | 
			
		||||
    if (count > 0) {
 | 
			
		||||
      *os << ' ';
 | 
			
		||||
    }
 | 
			
		||||
    *os << '}';
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
class TypeWithoutFormatter<T, kConvertibleToInteger> {
 | 
			
		||||
 public:
 | 
			
		||||
  // Since T has no << operator or PrintTo() but can be implicitly
 | 
			
		||||
  // converted to BiggestInt, we print it as a BiggestInt.
 | 
			
		||||
  //
 | 
			
		||||
  // Most likely T is an enum type (either named or unnamed), in which
 | 
			
		||||
  // case printing it as an integer is the desired behavior.  In case
 | 
			
		||||
  // T is not an enum, printing it as an integer is the best we can do
 | 
			
		||||
  // given that it has no user-defined printer.
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os) {
 | 
			
		||||
    const internal::BiggestInt kBigInt = value;
 | 
			
		||||
    *os << kBigInt;
 | 
			
		||||
// Used to print a pointer that is neither a char pointer nor a member
 | 
			
		||||
// pointer, when the user doesn't define PrintTo() for it.  (A member
 | 
			
		||||
// variable pointer or member function pointer doesn't really point to
 | 
			
		||||
// a location in the address space.  Their representation is
 | 
			
		||||
// implementation-defined.  Therefore they will be printed as raw
 | 
			
		||||
// bytes.)
 | 
			
		||||
struct FunctionPointerPrinter {
 | 
			
		||||
  template <typename T, typename = typename std::enable_if<
 | 
			
		||||
                            std::is_function<T>::value>::type>
 | 
			
		||||
  static void PrintValue(T* p, ::std::ostream* os) {
 | 
			
		||||
    if (p == nullptr) {
 | 
			
		||||
      *os << "NULL";
 | 
			
		||||
    } else {
 | 
			
		||||
      // T is a function type, so '*os << p' doesn't do what we want
 | 
			
		||||
      // (it just prints p as bool).  We want to print p as a const
 | 
			
		||||
      // void*.
 | 
			
		||||
      *os << reinterpret_cast<const void*>(p);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
 | 
			
		||||
template <typename T>
 | 
			
		||||
class TypeWithoutFormatter<T, kConvertibleToStringView> {
 | 
			
		||||
 public:
 | 
			
		||||
  // Since T has neither operator<< nor PrintTo() but can be implicitly
 | 
			
		||||
  // converted to absl::string_view, we print it as a absl::string_view
 | 
			
		||||
  // (or std::string_view).
 | 
			
		||||
  //
 | 
			
		||||
  // Note: the implementation is further below, as it depends on
 | 
			
		||||
  // internal::PrintTo symbol which is defined later in the file.
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os);
 | 
			
		||||
struct PointerPrinter {
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  static void PrintValue(T* p, ::std::ostream* os) {
 | 
			
		||||
    if (p == nullptr) {
 | 
			
		||||
      *os << "NULL";
 | 
			
		||||
    } else {
 | 
			
		||||
      // T is not a function type.  We just call << to print p,
 | 
			
		||||
      // relying on ADL to pick up user-defined << for their pointer
 | 
			
		||||
      // types, if any.
 | 
			
		||||
      *os << p;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Prints the given value to the given ostream.  If the value is a
 | 
			
		||||
// protocol message, its debug string is printed; if it's an enum or
 | 
			
		||||
// of a type implicitly convertible to BiggestInt, it's printed as an
 | 
			
		||||
// integer; otherwise the bytes in the value are printed.  This is
 | 
			
		||||
// what UniversalPrinter<T>::Print() does when it knows nothing about
 | 
			
		||||
// type T and T has neither << operator nor PrintTo().
 | 
			
		||||
namespace internal_stream {
 | 
			
		||||
 | 
			
		||||
struct Sentinel;
 | 
			
		||||
template <typename Char, typename CharTraits, typename T>
 | 
			
		||||
Sentinel* operator<<(::std::basic_ostream<Char, CharTraits>& os, const T& x);
 | 
			
		||||
 | 
			
		||||
// Check if the user has a user-defined operator<< for their type.
 | 
			
		||||
//
 | 
			
		||||
// A user can override this behavior for a class type Foo by defining
 | 
			
		||||
// a << operator in the namespace where Foo is defined.
 | 
			
		||||
//
 | 
			
		||||
// We put this operator in namespace 'internal2' instead of 'internal'
 | 
			
		||||
// to simplify the implementation, as much code in 'internal' needs to
 | 
			
		||||
// use << in STL, which would conflict with our own << were it defined
 | 
			
		||||
// in 'internal'.
 | 
			
		||||
// We put this in its own namespace to inject a custom operator<< that allows us
 | 
			
		||||
// to probe the type's operator.
 | 
			
		||||
//
 | 
			
		||||
// Note that this operator<< takes a generic std::basic_ostream<Char,
 | 
			
		||||
// CharTraits> type instead of the more restricted std::ostream.  If
 | 
			
		||||
@@ -229,67 +214,105 @@ class TypeWithoutFormatter<T, kConvertibleToStringView> {
 | 
			
		||||
// operator<<(std::ostream&, const T&) or
 | 
			
		||||
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
 | 
			
		||||
// specific.
 | 
			
		||||
template <typename Char, typename CharTraits, typename T>
 | 
			
		||||
::std::basic_ostream<Char, CharTraits>& operator<<(
 | 
			
		||||
    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
 | 
			
		||||
  TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value
 | 
			
		||||
                               ? kProtobuf
 | 
			
		||||
                               : std::is_convertible<
 | 
			
		||||
                                     const T&, internal::BiggestInt>::value
 | 
			
		||||
                                     ? kConvertibleToInteger
 | 
			
		||||
                                     :
 | 
			
		||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
 | 
			
		||||
                                     std::is_convertible<
 | 
			
		||||
                                         const T&, internal::StringView>::value
 | 
			
		||||
                                         ? kConvertibleToStringView
 | 
			
		||||
                                         :
 | 
			
		||||
#endif
 | 
			
		||||
                                         kOtherType)>::PrintValue(x, &os);
 | 
			
		||||
  return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace internal2
 | 
			
		||||
}  // namespace testing
 | 
			
		||||
 | 
			
		||||
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
 | 
			
		||||
// magic needed for implementing UniversalPrinter won't work.
 | 
			
		||||
namespace testing_internal {
 | 
			
		||||
 | 
			
		||||
// Used to print a value that is not an STL-style container when the
 | 
			
		||||
// user doesn't define PrintTo() for it.
 | 
			
		||||
template <typename T>
 | 
			
		||||
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
 | 
			
		||||
  // With the following statement, during unqualified name lookup,
 | 
			
		||||
  // testing::internal2::operator<< appears as if it was declared in
 | 
			
		||||
  // the nearest enclosing namespace that contains both
 | 
			
		||||
  // ::testing_internal and ::testing::internal2, i.e. the global
 | 
			
		||||
  // namespace.  For more details, refer to the C++ Standard section
 | 
			
		||||
  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
 | 
			
		||||
  // testing::internal2::operator<< in case T doesn't come with a <<
 | 
			
		||||
  // operator.
 | 
			
		||||
 | 
			
		||||
  using ::testing::internal2::operator<<;
 | 
			
		||||
 | 
			
		||||
  // Assuming T is defined in namespace foo, in the next statement,
 | 
			
		||||
  // the compiler will consider all of:
 | 
			
		||||
  //
 | 
			
		||||
  //   1. foo::operator<< (thanks to Koenig look-up),
 | 
			
		||||
  //   2. ::operator<< (as the current namespace is enclosed in ::),
 | 
			
		||||
  //   3. testing::internal2::operator<< (thanks to the using statement above).
 | 
			
		||||
  //
 | 
			
		||||
  // The operator<< whose type matches T best will be picked.
 | 
			
		||||
  //
 | 
			
		||||
  // We deliberately allow #2 to be a candidate, as sometimes it's
 | 
			
		||||
  // impossible to define #1 (e.g. when foo is ::std, defining
 | 
			
		||||
  // anything in it is undefined behavior unless you are a compiler
 | 
			
		||||
  // vendor.).
 | 
			
		||||
  *os << value;
 | 
			
		||||
constexpr bool UseStreamOperator() {
 | 
			
		||||
  return !std::is_same<decltype(std::declval<std::ostream&>()
 | 
			
		||||
                                << std::declval<const T&>()),
 | 
			
		||||
                       Sentinel*>::value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace testing_internal
 | 
			
		||||
}  // namespace internal_stream
 | 
			
		||||
 | 
			
		||||
namespace testing {
 | 
			
		||||
namespace internal {
 | 
			
		||||
struct StreamPrinter {
 | 
			
		||||
  template <typename T, typename = typename std::enable_if<
 | 
			
		||||
                            internal_stream::UseStreamOperator<T>()>::type>
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os) {
 | 
			
		||||
    *os << value;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ProtobufPrinter {
 | 
			
		||||
  // We print a protobuf using its ShortDebugString() when the string
 | 
			
		||||
  // doesn't exceed this many characters; otherwise we print it using
 | 
			
		||||
  // DebugString() for better readability.
 | 
			
		||||
  static const size_t kProtobufOneLinerMaxLength = 50;
 | 
			
		||||
 | 
			
		||||
  template <typename T, typename = typename std::enable_if<
 | 
			
		||||
                            internal::IsAProtocolMessage<T>::value>::type>
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os) {
 | 
			
		||||
    std::string pretty_str = value.ShortDebugString();
 | 
			
		||||
    if (pretty_str.length() > kProtobufOneLinerMaxLength) {
 | 
			
		||||
      pretty_str = "\n" + value.DebugString();
 | 
			
		||||
    }
 | 
			
		||||
    *os << ("<" + pretty_str + ">");
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ConvertibleToIntegerPrinter {
 | 
			
		||||
  // Since T has no << operator or PrintTo() but can be implicitly
 | 
			
		||||
  // converted to BiggestInt, we print it as a BiggestInt.
 | 
			
		||||
  //
 | 
			
		||||
  // Most likely T is an enum type (either named or unnamed), in which
 | 
			
		||||
  // case printing it as an integer is the desired behavior.  In case
 | 
			
		||||
  // T is not an enum, printing it as an integer is the best we can do
 | 
			
		||||
  // given that it has no user-defined printer.
 | 
			
		||||
  static void PrintValue(internal::BiggestInt value, ::std::ostream* os) {
 | 
			
		||||
    *os << value;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ConvertibleToStringViewPrinter {
 | 
			
		||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
 | 
			
		||||
  static void PrintValue(internal::StringView value, ::std::ostream* os) {
 | 
			
		||||
    internal::UniversalPrint(value, os);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Prints the given number of bytes in the given object to the given
 | 
			
		||||
// ostream.
 | 
			
		||||
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
 | 
			
		||||
                                     size_t count,
 | 
			
		||||
                                     ::std::ostream* os);
 | 
			
		||||
struct FallbackPrinter {
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  static void PrintValue(const T& value, ::std::ostream* os) {
 | 
			
		||||
    PrintBytesInObjectTo(
 | 
			
		||||
        static_cast<const unsigned char*>(
 | 
			
		||||
            reinterpret_cast<const void*>(std::addressof(value))),
 | 
			
		||||
        sizeof(value), os);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Try every printer in order and return the first one that works.
 | 
			
		||||
template <typename T, typename E, typename Printer, typename... Printers>
 | 
			
		||||
struct FindFirstPrinter : FindFirstPrinter<T, E, Printers...> {};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Printer, typename... Printers>
 | 
			
		||||
struct FindFirstPrinter<
 | 
			
		||||
    T, decltype(Printer::PrintValue(std::declval<const T&>(), nullptr)),
 | 
			
		||||
    Printer, Printers...> {
 | 
			
		||||
  using type = Printer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Select the best printer in the following order:
 | 
			
		||||
//  - Print containers (they have begin/end/etc).
 | 
			
		||||
//  - Print function pointers.
 | 
			
		||||
//  - Print object pointers.
 | 
			
		||||
//  - Use the stream operator, if available.
 | 
			
		||||
//  - Print protocol buffers.
 | 
			
		||||
//  - Print types convertible to BiggestInt.
 | 
			
		||||
//  - Print types convertible to StringView, if available.
 | 
			
		||||
//  - Fallback to printing the raw bytes of the object.
 | 
			
		||||
template <typename T>
 | 
			
		||||
void PrintWithFallback(const T& value, ::std::ostream* os) {
 | 
			
		||||
  using Printer = typename FindFirstPrinter<
 | 
			
		||||
      T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter,
 | 
			
		||||
      StreamPrinter, ProtobufPrinter, ConvertibleToIntegerPrinter,
 | 
			
		||||
      ConvertibleToStringViewPrinter, FallbackPrinter>::type;
 | 
			
		||||
  Printer::PrintValue(value, os);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
 | 
			
		||||
// value of type ToPrint that is an operand of a comparison assertion
 | 
			
		||||
@@ -388,85 +411,6 @@ std::string FormatForComparisonFailureMessage(
 | 
			
		||||
template <typename T>
 | 
			
		||||
class UniversalPrinter;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
void UniversalPrint(const T& value, ::std::ostream* os);
 | 
			
		||||
 | 
			
		||||
enum DefaultPrinterType {
 | 
			
		||||
  kPrintContainer,
 | 
			
		||||
  kPrintPointer,
 | 
			
		||||
  kPrintFunctionPointer,
 | 
			
		||||
  kPrintOther,
 | 
			
		||||
};
 | 
			
		||||
template <DefaultPrinterType type> struct WrapPrinterType {};
 | 
			
		||||
 | 
			
		||||
// Used to print an STL-style container when the user doesn't define
 | 
			
		||||
// a PrintTo() for it.
 | 
			
		||||
template <typename C>
 | 
			
		||||
void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
 | 
			
		||||
                    const C& container, ::std::ostream* os) {
 | 
			
		||||
  const size_t kMaxCount = 32;  // The maximum number of elements to print.
 | 
			
		||||
  *os << '{';
 | 
			
		||||
  size_t count = 0;
 | 
			
		||||
  for (typename C::const_iterator it = container.begin();
 | 
			
		||||
       it != container.end(); ++it, ++count) {
 | 
			
		||||
    if (count > 0) {
 | 
			
		||||
      *os << ',';
 | 
			
		||||
      if (count == kMaxCount) {  // Enough has been printed.
 | 
			
		||||
        *os << " ...";
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    *os << ' ';
 | 
			
		||||
    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
 | 
			
		||||
    // handle *it being a native array.
 | 
			
		||||
    internal::UniversalPrint(*it, os);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (count > 0) {
 | 
			
		||||
    *os << ' ';
 | 
			
		||||
  }
 | 
			
		||||
  *os << '}';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Used to print a pointer that is neither a char pointer nor a member
 | 
			
		||||
// pointer, when the user doesn't define PrintTo() for it.  (A member
 | 
			
		||||
// variable pointer or member function pointer doesn't really point to
 | 
			
		||||
// a location in the address space.  Their representation is
 | 
			
		||||
// implementation-defined.  Therefore they will be printed as raw
 | 
			
		||||
// bytes.)
 | 
			
		||||
template <typename T>
 | 
			
		||||
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
 | 
			
		||||
                    T* p, ::std::ostream* os) {
 | 
			
		||||
  if (p == nullptr) {
 | 
			
		||||
    *os << "NULL";
 | 
			
		||||
  } else {
 | 
			
		||||
    // T is not a function type.  We just call << to print p,
 | 
			
		||||
    // relying on ADL to pick up user-defined << for their pointer
 | 
			
		||||
    // types, if any.
 | 
			
		||||
    *os << p;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
template <typename T>
 | 
			
		||||
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
 | 
			
		||||
                    T* p, ::std::ostream* os) {
 | 
			
		||||
  if (p == nullptr) {
 | 
			
		||||
    *os << "NULL";
 | 
			
		||||
  } else {
 | 
			
		||||
    // T is a function type, so '*os << p' doesn't do what we want
 | 
			
		||||
    // (it just prints p as bool).  We want to print p as a const
 | 
			
		||||
    // void*.
 | 
			
		||||
    *os << reinterpret_cast<const void*>(p);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Used to print a non-container, non-pointer value when the user
 | 
			
		||||
// doesn't define PrintTo() for it.
 | 
			
		||||
template <typename T>
 | 
			
		||||
void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
 | 
			
		||||
                    const T& value, ::std::ostream* os) {
 | 
			
		||||
  ::testing_internal::DefaultPrintNonContainerTo(value, os);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Prints the given value using the << operator if it has one;
 | 
			
		||||
// otherwise prints the bytes in it.  This is what
 | 
			
		||||
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
 | 
			
		||||
@@ -480,36 +424,7 @@ void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
 | 
			
		||||
// wants).
 | 
			
		||||
template <typename T>
 | 
			
		||||
void PrintTo(const T& value, ::std::ostream* os) {
 | 
			
		||||
  // DefaultPrintTo() is overloaded.  The type of its first argument
 | 
			
		||||
  // determines which version will be picked.
 | 
			
		||||
  //
 | 
			
		||||
  // Note that we check for container types here, prior to we check
 | 
			
		||||
  // for protocol message types in our operator<<.  The rationale is:
 | 
			
		||||
  //
 | 
			
		||||
  // For protocol messages, we want to give people a chance to
 | 
			
		||||
  // override Google Mock's format by defining a PrintTo() or
 | 
			
		||||
  // operator<<.  For STL containers, other formats can be
 | 
			
		||||
  // incompatible with Google Mock's format for the container
 | 
			
		||||
  // elements; therefore we check for container types here to ensure
 | 
			
		||||
  // that our format is used.
 | 
			
		||||
  //
 | 
			
		||||
  // Note that MSVC and clang-cl do allow an implicit conversion from
 | 
			
		||||
  // pointer-to-function to pointer-to-object, but clang-cl warns on it.
 | 
			
		||||
  // So don't use ImplicitlyConvertible if it can be helped since it will
 | 
			
		||||
  // cause this warning, and use a separate overload of DefaultPrintTo for
 | 
			
		||||
  // function pointers so that the `*os << p` in the object pointer overload
 | 
			
		||||
  // doesn't cause that warning either.
 | 
			
		||||
  DefaultPrintTo(
 | 
			
		||||
      WrapPrinterType <
 | 
			
		||||
                  (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
 | 
			
		||||
              !IsRecursiveContainer<T>::value
 | 
			
		||||
          ? kPrintContainer
 | 
			
		||||
          : !std::is_pointer<T>::value
 | 
			
		||||
                ? kPrintOther
 | 
			
		||||
                : std::is_function<typename std::remove_pointer<T>::type>::value
 | 
			
		||||
                      ? kPrintFunctionPointer
 | 
			
		||||
                      : kPrintPointer > (),
 | 
			
		||||
      value, os);
 | 
			
		||||
  internal::PrintWithFallback(value, os);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The following list of PrintTo() overloads tells
 | 
			
		||||
@@ -900,16 +815,6 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
 | 
			
		||||
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
#if GTEST_INTERNAL_HAS_STRING_VIEW
 | 
			
		||||
namespace internal2 {
 | 
			
		||||
template <typename T>
 | 
			
		||||
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
 | 
			
		||||
    const T& value, ::std::ostream* os) {
 | 
			
		||||
  internal::PrintTo(internal::StringView(value), os);
 | 
			
		||||
}
 | 
			
		||||
}  // namespace internal2
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
::std::string PrintToString(const T& value) {
 | 
			
		||||
  ::std::stringstream ss;
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,7 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
namespace internal2 {
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
 | 
			
		||||
// given object.  The delegation simplifies the implementation, which
 | 
			
		||||
@@ -116,10 +116,6 @@ void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
 | 
			
		||||
  PrintBytesInObjectToImpl(obj_bytes, count, os);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace internal2
 | 
			
		||||
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
// Depending on the value of a char (or wchar_t), we print it in one
 | 
			
		||||
// of three formats:
 | 
			
		||||
//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user