mirror of
https://github.com/google/googletest.git
synced 2025-03-10 17:36:10 +00:00
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.
This commit is contained in:
parent
603533a0a4
commit
5451ffe816
@ -742,7 +742,8 @@ struct TuplePrefixPrinter<0> {
|
|||||||
// We have to specialize the entire TuplePrefixPrinter<> class
|
// We have to specialize the entire TuplePrefixPrinter<> class
|
||||||
// template here, even though the definition of
|
// template here, even though the definition of
|
||||||
// TersePrintPrefixToStrings() is the same as the generic version, as
|
// 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 <>
|
template <>
|
||||||
struct TuplePrefixPrinter<1> {
|
struct TuplePrefixPrinter<1> {
|
||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
|
@ -896,21 +896,38 @@ struct IsAProtocolMessage
|
|||||||
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
|
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// When the compiler sees expression IsContainerTest<C>(0), the first
|
// When the compiler sees expression IsContainerTest<C>(0), if C is an
|
||||||
// overload of IsContainerTest will be picked if C is an STL-style
|
// STL-style container class, the first overload of IsContainerTest
|
||||||
// container class (since C::const_iterator* is a valid type and 0 can
|
// will be viable (since both C::iterator* and C::const_iterator* are
|
||||||
// be converted to it), while the second overload will be picked
|
// valid types and NULL can be implicitly converted to them). It will
|
||||||
// otherwise (since C::const_iterator will be an invalid type in this
|
// be picked over the second overload as 'int' is a perfect match for
|
||||||
// case). Therefore, we can determine whether C is a container class
|
// the type of argument 0. If C::iterator or C::const_iterator is not
|
||||||
// by checking the type of IsContainerTest<C>(0). The value of the
|
// a valid type, the first overload is not viable, and the second
|
||||||
// expression is insignificant.
|
// 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;
|
typedef int IsContainer;
|
||||||
template <class C>
|
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;
|
typedef char IsNotContainer;
|
||||||
template <class C>
|
template <class C>
|
||||||
IsNotContainer IsContainerTest(...) { return '\0'; }
|
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
|
||||||
|
|
||||||
// EnableIf<condition>::type is void when 'Cond' is true, and
|
// EnableIf<condition>::type is void when 'Cond' is true, and
|
||||||
// undefined when 'Cond' is false. To use SFINAE to make a function
|
// undefined when 'Cond' is false. To use SFINAE to make a function
|
||||||
@ -1009,6 +1026,7 @@ class NativeArray {
|
|||||||
public:
|
public:
|
||||||
// STL-style container typedefs.
|
// STL-style container typedefs.
|
||||||
typedef Element value_type;
|
typedef Element value_type;
|
||||||
|
typedef Element* iterator;
|
||||||
typedef const Element* const_iterator;
|
typedef const Element* const_iterator;
|
||||||
|
|
||||||
// Constructs from a native array.
|
// Constructs from a native array.
|
||||||
|
@ -936,6 +936,28 @@ TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
|
|||||||
EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
|
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
|
#if GTEST_HAS_TR1_TUPLE
|
||||||
// Tests printing tuples.
|
// Tests printing tuples.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user