Merge pull request #1508 from gennadiycivil/master
merge, again, IsRecursiveContainer
This commit is contained in:
commit
dccc2d6754
|
@ -509,17 +509,19 @@ void PrintTo(const T& value, ::std::ostream* os) {
|
||||||
// function pointers so that the `*os << p` in the object pointer overload
|
// function pointers so that the `*os << p` in the object pointer overload
|
||||||
// doesn't cause that warning either.
|
// doesn't cause that warning either.
|
||||||
DefaultPrintTo(
|
DefaultPrintTo(
|
||||||
WrapPrinterType<
|
WrapPrinterType <
|
||||||
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && !IsRecursiveContainer<T>::value
|
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
|
||||||
? kPrintContainer : !is_pointer<T>::value
|
!IsRecursiveContainer<T>::value
|
||||||
? kPrintOther
|
? kPrintContainer
|
||||||
|
: !is_pointer<T>::value
|
||||||
|
? kPrintOther
|
||||||
#if GTEST_LANG_CXX11
|
#if GTEST_LANG_CXX11
|
||||||
: std::is_function<typename std::remove_pointer<T>::type>::value
|
: std::is_function<typename std::remove_pointer<T>::type>::value
|
||||||
#else
|
#else
|
||||||
: !internal::ImplicitlyConvertible<T, const void*>::value
|
: !internal::ImplicitlyConvertible<T, const void*>::value
|
||||||
#endif
|
#endif
|
||||||
? kPrintFunctionPointer
|
? kPrintFunctionPointer
|
||||||
: kPrintPointer>(),
|
: kPrintPointer > (),
|
||||||
value, os);
|
value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -875,8 +875,11 @@ struct IsAProtocolMessage
|
||||||
// a container class by checking the type of IsContainerTest<C>(0).
|
// a container class by checking the type of IsContainerTest<C>(0).
|
||||||
// The value of the expression is insignificant.
|
// The value of the expression is insignificant.
|
||||||
//
|
//
|
||||||
// Note that we look for both C::iterator and C::const_iterator. The
|
// In C++11 mode we check the existence of a const_iterator and that an
|
||||||
// reason is that C++ injects the name of a class as a member of the
|
// 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
|
// class itself (e.g. you can refer to class iterator as either
|
||||||
// 'iterator' or 'iterator::iterator'). If we look for C::iterator
|
// 'iterator' or 'iterator::iterator'). If we look for C::iterator
|
||||||
// only, for example, we would mistakenly think that a class named
|
// only, for example, we would mistakenly think that a class named
|
||||||
|
@ -886,40 +889,94 @@ struct IsAProtocolMessage
|
||||||
// IsContainerTest(typename C::const_iterator*) and
|
// IsContainerTest(typename C::const_iterator*) and
|
||||||
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
|
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
|
||||||
typedef int IsContainer;
|
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>
|
template <class C>
|
||||||
IsContainer IsContainerTest(int /* dummy */,
|
IsContainer IsContainerTest(int /* dummy */,
|
||||||
typename C::iterator* /* it */ = NULL,
|
typename C::iterator* /* it */ = NULL,
|
||||||
typename C::const_iterator* /* const_it */ = NULL) {
|
typename C::const_iterator* /* const_it */ = NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif // GTEST_LANG_CXX11
|
||||||
|
|
||||||
typedef char IsNotContainer;
|
typedef char IsNotContainer;
|
||||||
template <class C>
|
template <class C>
|
||||||
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
|
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
|
||||||
|
|
||||||
template <typename C, bool =
|
// Trait to detect whether a type T is a hash table.
|
||||||
sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)
|
// 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 T>
|
||||||
|
struct VoidT {
|
||||||
|
typedef void value_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct HasValueType : false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct HasValueType<T, VoidT<typename T::value_type> > : true_type {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename C,
|
||||||
|
bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer),
|
||||||
|
bool = HasValueType<C>::value>
|
||||||
struct IsRecursiveContainerImpl;
|
struct IsRecursiveContainerImpl;
|
||||||
|
|
||||||
|
template <typename C, bool HV>
|
||||||
|
struct IsRecursiveContainerImpl<C, false, HV> : public false_type {};
|
||||||
|
|
||||||
|
// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
|
||||||
|
// obey the same inconsistencies as the IsContainerTest, namely check if
|
||||||
|
// something is a container is relying on only const_iterator in C++11 and
|
||||||
|
// is relying on both const_iterator and iterator otherwise
|
||||||
template <typename C>
|
template <typename C>
|
||||||
struct IsRecursiveContainerImpl<C, false> : public false_type {};
|
struct IsRecursiveContainerImpl<C, true, false> : public false_type {};
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
struct IsRecursiveContainerImpl<C, true> {
|
struct IsRecursiveContainerImpl<C, true, true> {
|
||||||
typedef
|
#if GTEST_LANG_CXX11
|
||||||
typename IteratorTraits<typename C::iterator>::value_type
|
typedef typename IteratorTraits<typename C::const_iterator>::value_type
|
||||||
value_type;
|
value_type;
|
||||||
|
#else
|
||||||
|
typedef typename IteratorTraits<typename C::iterator>::value_type value_type;
|
||||||
|
#endif
|
||||||
typedef is_same<value_type, C> type;
|
typedef is_same<value_type, C> type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// IsRecursiveContainer<Type> is a unary compile-time predicate that
|
// 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
|
// type is a container type whose value_type is equal to the container type
|
||||||
// itself. An example for a recursive container type is
|
// 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, whose iterator has a value_type that is equal to
|
||||||
// boost::filesystem::path.
|
// boost::filesystem::path.
|
||||||
template<typename C>
|
template <typename C>
|
||||||
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
|
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
|
||||||
|
|
||||||
// EnableIf<condition>::type is void when 'Cond' is true, and
|
// EnableIf<condition>::type is void when 'Cond' is true, and
|
||||||
|
@ -1218,4 +1275,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()
|
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
|
||||||
|
|
||||||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
|
||||||
|
|
||||||
|
|
|
@ -5185,8 +5185,8 @@ bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
|
||||||
// each TestCase and TestInfo object.
|
// each TestCase and TestInfo object.
|
||||||
// If shard_tests == true, further filters tests based on sharding
|
// If shard_tests == true, further filters tests based on sharding
|
||||||
// variables in the environment - see
|
// variables in the environment - see
|
||||||
// https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md .
|
// https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md
|
||||||
// Returns the number of tests that should run.
|
// . Returns the number of tests that should run.
|
||||||
int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
|
||||||
const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
|
const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
|
||||||
Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
|
Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
|
||||||
|
|
|
@ -195,7 +195,6 @@ class PathLike {
|
||||||
struct iterator {
|
struct iterator {
|
||||||
typedef PathLike value_type;
|
typedef PathLike value_type;
|
||||||
};
|
};
|
||||||
typedef iterator const_iterator;
|
|
||||||
|
|
||||||
PathLike() {}
|
PathLike() {}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,9 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#if GTEST_LANG_CXX11
|
||||||
|
#include <unordered_set>
|
||||||
|
#endif // GTEST_LANG_CXX11
|
||||||
|
|
||||||
#include "gtest/gtest-spi.h"
|
#include "gtest/gtest-spi.h"
|
||||||
#include "src/gtest-internal-inl.h"
|
#include "src/gtest-internal-inl.h"
|
||||||
|
@ -258,6 +261,8 @@ using testing::internal::IsContainer;
|
||||||
using testing::internal::IsContainerTest;
|
using testing::internal::IsContainerTest;
|
||||||
using testing::internal::IsNotContainer;
|
using testing::internal::IsNotContainer;
|
||||||
using testing::internal::NativeArray;
|
using testing::internal::NativeArray;
|
||||||
|
using testing::internal::OsStackTraceGetter;
|
||||||
|
using testing::internal::OsStackTraceGetterInterface;
|
||||||
using testing::internal::ParseInt32Flag;
|
using testing::internal::ParseInt32Flag;
|
||||||
using testing::internal::RelationToSourceCopy;
|
using testing::internal::RelationToSourceCopy;
|
||||||
using testing::internal::RelationToSourceReference;
|
using testing::internal::RelationToSourceReference;
|
||||||
|
@ -274,6 +279,7 @@ using testing::internal::String;
|
||||||
using testing::internal::TestEventListenersAccessor;
|
using testing::internal::TestEventListenersAccessor;
|
||||||
using testing::internal::TestResultAccessor;
|
using testing::internal::TestResultAccessor;
|
||||||
using testing::internal::UInt32;
|
using testing::internal::UInt32;
|
||||||
|
using testing::internal::UnitTestImpl;
|
||||||
using testing::internal::WideStringToUtf8;
|
using testing::internal::WideStringToUtf8;
|
||||||
using testing::internal::edit_distance::CalculateOptimalEdits;
|
using testing::internal::edit_distance::CalculateOptimalEdits;
|
||||||
using testing::internal::edit_distance::CreateUnifiedDiff;
|
using testing::internal::edit_distance::CreateUnifiedDiff;
|
||||||
|
@ -7526,6 +7532,50 @@ TEST(IsContainerTestTest, WorksForContainer) {
|
||||||
sizeof(IsContainerTest<std::map<int, double> >(0)));
|
sizeof(IsContainerTest<std::map<int, double> >(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GTEST_LANG_CXX11
|
||||||
|
struct ConstOnlyContainerWithPointerIterator {
|
||||||
|
using const_iterator = int*;
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConstOnlyContainerWithClassIterator {
|
||||||
|
struct const_iterator {
|
||||||
|
const int& operator*() const;
|
||||||
|
const_iterator& operator++(/* pre-increment */);
|
||||||
|
};
|
||||||
|
const_iterator begin() const;
|
||||||
|
const_iterator end() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(IsContainerTestTest, ConstOnlyContainer) {
|
||||||
|
EXPECT_EQ(sizeof(IsContainer),
|
||||||
|
sizeof(IsContainerTest<ConstOnlyContainerWithPointerIterator>(0)));
|
||||||
|
EXPECT_EQ(sizeof(IsContainer),
|
||||||
|
sizeof(IsContainerTest<ConstOnlyContainerWithClassIterator>(0)));
|
||||||
|
}
|
||||||
|
#endif // GTEST_LANG_CXX11
|
||||||
|
|
||||||
|
// Tests IsHashTable.
|
||||||
|
struct AHashTable {
|
||||||
|
typedef void hasher;
|
||||||
|
};
|
||||||
|
struct NotReallyAHashTable {
|
||||||
|
typedef void hasher;
|
||||||
|
typedef void reverse_iterator;
|
||||||
|
};
|
||||||
|
TEST(IsHashTable, Basic) {
|
||||||
|
EXPECT_TRUE(testing::internal::IsHashTable<AHashTable>::value);
|
||||||
|
EXPECT_FALSE(testing::internal::IsHashTable<NotReallyAHashTable>::value);
|
||||||
|
#if GTEST_LANG_CXX11
|
||||||
|
EXPECT_FALSE(testing::internal::IsHashTable<std::vector<int>>::value);
|
||||||
|
EXPECT_TRUE(testing::internal::IsHashTable<std::unordered_set<int>>::value);
|
||||||
|
#endif // GTEST_LANG_CXX11
|
||||||
|
#if GTEST_HAS_HASH_SET_
|
||||||
|
EXPECT_TRUE(testing::internal::IsHashTable<hash_set<int>>::value);
|
||||||
|
#endif // GTEST_HAS_HASH_SET_
|
||||||
|
}
|
||||||
|
|
||||||
// Tests ArrayEq().
|
// Tests ArrayEq().
|
||||||
|
|
||||||
TEST(ArrayEqTest, WorksForDegeneratedArrays) {
|
TEST(ArrayEqTest, WorksForDegeneratedArrays) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user