aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2009-03-31 18:26:29 +0000
committerzhanyong.wan <zhanyong.wan@8415998a-534a-0410-bf83-d39667b30386>2009-03-31 18:26:29 +0000
commit7e571ef537f0eb17db4bbaf8a9c1a41a2839ab81 (patch)
tree201513439ecedf7da299bd1e0e732243bb50ff02 /include
parent946bc64fcf473b1bd87c51d4320d9483e270d9d2 (diff)
downloadgoogletest-7e571ef537f0eb17db4bbaf8a9c1a41a2839ab81.tar.gz
googletest-7e571ef537f0eb17db4bbaf8a9c1a41a2839ab81.tar.bz2
googletest-7e571ef537f0eb17db4bbaf8a9c1a41a2839ab81.zip
Makes googlemock compile with gcc 3.3.
Diffstat (limited to 'include')
-rw-r--r--include/gmock/gmock-printers.h87
1 files changed, 55 insertions, 32 deletions
diff --git a/include/gmock/gmock-printers.h b/include/gmock/gmock-printers.h
index 28e904c3..fa510ba2 100644
--- a/include/gmock/gmock-printers.h
+++ b/include/gmock/gmock-printers.h
@@ -36,11 +36,19 @@
//
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
//
-// It uses the << operator when possible, and prints the bytes in the
-// object otherwise. A user can override its behavior for a class
-// type Foo by defining either operator<<(::std::ostream&, const Foo&)
-// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
-// defines Foo. If both are defined, PrintTo() takes precedence.
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T. More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+// 1. foo::PrintTo(const T&, ostream*)
+// 2. operator<<(ostream&, const T&) defined in either foo or the
+// global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
//
// To aid debugging: when T is a reference type, the address of the
// value is also printed; when T is a (const) char pointer, both the
@@ -76,12 +84,6 @@
#include <gmock/internal/gmock-port.h>
#include <gtest/gtest.h>
-// Makes sure there is at least one << operator declared in the global
-// namespace. This has no implementation and won't be called
-// anywhere. We just need the declaration such that we can say "using
-// ::operator <<;" in the definition of PrintTo() below.
-void operator<<(::testing::internal::Unused, int);
-
namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are
@@ -152,7 +154,48 @@ template <typename Char, typename CharTraits, typename T>
}
} // 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.
+ //
+ // We cannot write 'using ::testing::internal2::operator<<;', which
+ // gcc 3.3 fails to compile due to a compiler bug.
+ using namespace ::testing::internal2; // NOLINT
+
+ // 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;
+}
+} // namespace testing_internal
+
+namespace testing {
namespace internal {
// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
@@ -194,27 +237,7 @@ void DefaultPrintTo(IsContainer, const C& container, ::std::ostream* os) {
// Used to print a value when the user doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintTo(IsNotContainer, const T& value, ::std::ostream* os) {
- // If T has its << operator defined in the global namespace, which
- // is not recommended but sometimes unavoidable (as in
- // util/gtl/stl_logging-inl.h), the following statement makes it
- // visible in this function.
- //
- // Without the statement, << in the global namespace would be hidden
- // by the one in ::testing::internal2, due to the next using
- // statement.
- using ::operator <<;
-
- // When T doesn't come with a << operator, we want to fall back to
- // the one defined in ::testing::internal2, which prints the bytes in
- // the value.
- using ::testing::internal2::operator <<;
-
- // Thanks to Koenig look-up, if type T has its own << operator
- // defined in its namespace, which is the recommended way, that
- // operator will be visible here. Since it is more specific than
- // the generic one, it will be picked by the compiler in the
- // following statement - exactly what we want.
- *os << value;
+ ::testing_internal::DefaultPrintNonContainerTo(value, os);
}
// Prints the given value using the << operator if it has one;