diff options
author | Gennadiy Civil <misterg@google.com> | 2018-03-15 18:31:37 (GMT) |
---|---|---|
committer | Gennadiy Civil <misterg@google.com> | 2018-03-15 18:31:37 (GMT) |
commit | a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b (patch) | |
tree | c0cdf002f62ce0af852a61777e009c9968ef806f /googletest/include/gtest/internal | |
parent | a325ad2db5deb623eab740527e559b81c0f39d65 (diff) | |
download | googletest-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.h | 75 |
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_ - |