summaryrefslogtreecommitdiffstats
path: root/googletest/include/gtest/internal
diff options
context:
space:
mode:
authorGennadiy Civil <misterg@google.com>2018-03-15 18:31:37 (GMT)
committerGennadiy Civil <misterg@google.com>2018-03-15 18:31:37 (GMT)
commita178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b (patch)
treec0cdf002f62ce0af852a61777e009c9968ef806f /googletest/include/gtest/internal
parenta325ad2db5deb623eab740527e559b81c0f39d65 (diff)
downloadgoogletest-a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b.zip
googletest-a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b.tar.gz
googletest-a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b.tar.bz2
merge, again, IsRecursiveContainerrefs/pull/1507/head
Diffstat (limited to 'googletest/include/gtest/internal')
-rw-r--r--googletest/include/gtest/internal/gtest-internal.h75
1 files changed, 62 insertions, 13 deletions
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h
index e87f85e..612f8a4 100644
--- a/googletest/include/gtest/internal/gtest-internal.h
+++ b/googletest/include/gtest/internal/gtest-internal.h
@@ -875,8 +875,11 @@ struct IsAProtocolMessage
// 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
+// In C++11 mode we check the existence of a const_iterator and that an
+// iterator is properly implemented for the container.
+//
+// For pre-C++11 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
@@ -886,20 +889,52 @@ struct IsAProtocolMessage
// IsContainerTest(typename C::const_iterator*) and
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
typedef int IsContainer;
+#if GTEST_LANG_CXX11
+template <class C,
+ class Iterator = decltype(::std::declval<const C&>().begin()),
+ class = decltype(::std::declval<const C&>().end()),
+ class = decltype(++::std::declval<Iterator&>()),
+ class = decltype(*::std::declval<Iterator>()),
+ class = typename C::const_iterator>
+IsContainer IsContainerTest(int /* dummy */) {
+ return 0;
+}
+#else
template <class C>
IsContainer IsContainerTest(int /* dummy */,
typename C::iterator* /* it */ = NULL,
typename C::const_iterator* /* const_it */ = NULL) {
return 0;
}
+#endif // GTEST_LANG_CXX11
typedef char IsNotContainer;
template <class C>
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
-template <typename C, bool =
- sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)
->
+// Trait to detect whether a type T is a hash table.
+// The heuristic used is that the type contains an inner type `hasher` and does
+// not contain an inner type `reverse_iterator`.
+// If the container is iterable in reverse, then order might actually matter.
+template <typename T>
+struct IsHashTable {
+ private:
+ template <typename U>
+ static char test(typename U::hasher*, typename U::reverse_iterator*);
+ template <typename U>
+ static int test(typename U::hasher*, ...);
+ template <typename U>
+ static char test(...);
+
+ public:
+ static const bool value = sizeof(test<T>(0, 0)) == sizeof(int);
+};
+
+template <typename T>
+const bool IsHashTable<T>::value;
+
+template <typename C,
+ bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
struct IsRecursiveContainerImpl;
template <typename C>
@@ -907,19 +942,34 @@ struct IsRecursiveContainerImpl<C, false> : public false_type {};
template <typename C>
struct IsRecursiveContainerImpl<C, true> {
- typedef
- typename IteratorTraits<typename C::iterator>::value_type
- value_type;
+ template <typename T>
+ struct VoidT {
+ typedef void value_type;
+ };
+ template <typename C1, typename VT = void>
+ struct PathTraits {
+ typedef typename C1::const_iterator::value_type value_type;
+ };
+ template <typename C2>
+ struct PathTraits<
+ C2, typename VoidT<typename C2::iterator::value_type>::value_type> {
+ typedef typename C2::iterator::value_type value_type;
+ };
+ typedef typename IteratorTraits<typename C::iterator>::value_type value_type;
+#if GTEST_LANG_CXX11
+ typedef std::is_same<value_type, C> type;
+#else
typedef is_same<value_type, C> type;
+#endif
};
// IsRecursiveContainer<Type> is a unary compile-time predicate that
-// evaluates whether C is a recursive container type. A recursive container
+// evaluates whether C is a recursive container type. A recursive container
// type is a container type whose value_type is equal to the container type
-// itself. An example for a recursive container type is
-// boost::filesystem::path, whose iterator has a value_type that is equal to
+// itself. An example for a recursive container type is
+// boost::filesystem::path, whose iterator has a value_type that is equal to
// boost::filesystem::path.
-template<typename C>
+template <typename C>
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
// EnableIf<condition>::type is void when 'Cond' is true, and
@@ -1218,4 +1268,3 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-