summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2011-03-09 01:13:19 +0000
committerzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2011-03-09 01:13:19 +0000
commit6c5116014ce51ef3273d800cbf75fcef99e798c6 (patch)
treefa0e72e4f75615101b80684a921222b52c6286dd
parented1042b09b7d6f7857ff3a4ad33acef08a016960 (diff)
downloadgtest-6c5116014ce51ef3273d800cbf75fcef99e798c6.tar.gz
gtest-6c5116014ce51ef3273d800cbf75fcef99e798c6.tar.bz2
gtest-6c5116014ce51ef3273d800cbf75fcef99e798c6.tar.xz
Makes IsContainerTest compatible with Sun C++ and Visual Age C++, based on Hady Zalek's report and experiment; also fixes a bug that causes it to think that a class named const_iterator is a container; also clarifies the Borland C++ compatibility fix in the comments based on Josh Kelley's suggestion.
git-svn-id: http://googletest.googlecode.com/svn/trunk@554 861a406c-534a-0410-8894-cb66d6ee9925
-rw-r--r--include/gtest/gtest-printers.h3
-rw-r--r--include/gtest/internal/gtest-internal.h38
-rw-r--r--test/gtest-printers_test.cc22
3 files changed, 52 insertions, 11 deletions
diff --git a/include/gtest/gtest-printers.h b/include/gtest/gtest-printers.h
index cbb809f..9cbab3f 100644
--- a/include/gtest/gtest-printers.h
+++ b/include/gtest/gtest-printers.h
@@ -742,7 +742,8 @@ struct TuplePrefixPrinter<0> {
// We have to specialize the entire TuplePrefixPrinter<> class
// template here, even though the definition of
// TersePrintPrefixToStrings() is the same as the generic version, as
-// Borland C++ doesn't support specializing a method.
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
template <>
struct TuplePrefixPrinter<1> {
template <typename Tuple>
diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h
index 947b162..cfa3885 100644
--- a/include/gtest/internal/gtest-internal.h
+++ b/include/gtest/internal/gtest-internal.h
@@ -896,21 +896,38 @@ struct IsAProtocolMessage
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
};
-// When the compiler sees expression IsContainerTest<C>(0), the first
-// overload of IsContainerTest will be picked if C is an STL-style
-// container class (since C::const_iterator* is a valid type and 0 can
-// be converted to it), while the second overload will be picked
-// otherwise (since C::const_iterator will be an invalid type in this
-// case). Therefore, we can determine whether C is a container class
-// by checking the type of IsContainerTest<C>(0). The value of the
-// expression is insignificant.
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them). It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0. If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked. Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator. The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator'). If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
typedef int IsContainer;
template <class C>
-IsContainer IsContainerTest(typename C::const_iterator*) { return 0; }
+IsContainer IsContainerTest(int /* dummy */,
+ typename C::iterator* /* it */ = NULL,
+ typename C::const_iterator* /* const_it */ = NULL) {
+ return 0;
+}
typedef char IsNotContainer;
template <class C>
-IsNotContainer IsContainerTest(...) { return '\0'; }
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
// EnableIf<condition>::type is void when 'Cond' is true, and
// undefined when 'Cond' is false. To use SFINAE to make a function
@@ -1009,6 +1026,7 @@ class NativeArray {
public:
// STL-style container typedefs.
typedef Element value_type;
+ typedef Element* iterator;
typedef const Element* const_iterator;
// Constructs from a native array.
diff --git a/test/gtest-printers_test.cc b/test/gtest-printers_test.cc
index 8992a9a..e0065e2 100644
--- a/test/gtest-printers_test.cc
+++ b/test/gtest-printers_test.cc
@@ -936,6 +936,28 @@ TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
}
+// Tests that a class named iterator isn't treated as a container.
+
+struct iterator {
+ char x;
+};
+
+TEST(PrintStlContainerTest, Iterator) {
+ iterator it = {};
+ EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
+// Tests that a class named const_iterator isn't treated as a container.
+
+struct const_iterator {
+ char x;
+};
+
+TEST(PrintStlContainerTest, ConstIterator) {
+ const_iterator it = {};
+ EXPECT_EQ("1-byte object <00>", Print(it));
+}
+
#if GTEST_HAS_TR1_TUPLE
// Tests printing tuples.