summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-10-10 17:12:54 (GMT)
committerGennadiy Civil <misterg@google.com>2019-10-11 11:06:56 (GMT)
commited78e54f38ab10c775e39e5c4d500c6134a60d64 (patch)
treed911208bec3165eeaaf5a12f48181d25aa7be489
parent58c71977611c0019cf077e43fb54bc3326409a43 (diff)
downloadgoogletest-ed78e54f38ab10c775e39e5c4d500c6134a60d64.zip
googletest-ed78e54f38ab10c775e39e5c4d500c6134a60d64.tar.gz
googletest-ed78e54f38ab10c775e39e5c4d500c6134a60d64.tar.bz2
Googletest export
Fix the O(n^2) number of instantiations in ElemFromList. It is now O(n). It still has O(1) instantiation depth. PiperOrigin-RevId: 273980821
-rw-r--r--googlemock/include/gmock/internal/gmock-internal-utils.h3
-rw-r--r--googletest/include/gtest/internal/gtest-internal.h44
-rw-r--r--googletest/test/gtest_unittest.cc17
3 files changed, 30 insertions, 34 deletions
diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h
index d012e71..584afa9 100644
--- a/googlemock/include/gmock/internal/gmock-internal-utils.h
+++ b/googlemock/include/gmock/internal/gmock-internal-utils.h
@@ -490,8 +490,7 @@ struct Function<R(Args...)> {
using Result = R;
static constexpr size_t ArgumentCount = sizeof...(Args);
template <size_t I>
- using Arg = ElemFromList<I, typename MakeIndexSequence<sizeof...(Args)>::type,
- Args...>;
+ using Arg = ElemFromList<I, Args...>;
using ArgumentTuple = std::tuple<Args...>;
using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>;
using MakeResultVoid = void(Args...);
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h
index 76ce13a..ebfe3c9 100644
--- a/googletest/include/gtest/internal/gtest-internal.h
+++ b/googletest/include/gtest/internal/gtest-internal.h
@@ -1124,25 +1124,29 @@ struct MakeIndexSequence
template <>
struct MakeIndexSequence<0> : IndexSequence<> {};
-// FIXME: This implementation of ElemFromList is O(1) in instantiation depth,
-// but it is O(N^2) in total instantiations. Not sure if this is the best
-// tradeoff, as it will make it somewhat slow to compile.
-template <typename T, size_t, size_t>
-struct ElemFromListImpl {};
-
-template <typename T, size_t I>
-struct ElemFromListImpl<T, I, I> {
- using type = T;
+template <size_t>
+struct Ignore {
+ Ignore(...); // NOLINT
};
-// Get the Nth element from T...
-// It uses O(1) instantiation depth.
-template <size_t N, typename I, typename... T>
-struct ElemFromList;
+template <typename>
+struct ElemFromListImpl;
+template <size_t... I>
+struct ElemFromListImpl<IndexSequence<I...>> {
+ // We make Ignore a template to solve a problem with MSVC.
+ // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but
+ // MSVC doesn't understand how to deal with that pack expansion.
+ // Use `0 * I` to have a single instantiation of Ignore.
+ template <typename R>
+ static R Apply(Ignore<0 * I>..., R (*)(), ...);
+};
-template <size_t N, size_t... I, typename... T>
-struct ElemFromList<N, IndexSequence<I...>, T...>
- : ElemFromListImpl<T, N, I>... {};
+template <size_t N, typename... T>
+struct ElemFromList {
+ using type =
+ decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply(
+ static_cast<T (*)()>(nullptr)...));
+};
template <typename... T>
class FlatTuple;
@@ -1152,9 +1156,7 @@ struct FlatTupleElemBase;
template <typename... T, size_t I>
struct FlatTupleElemBase<FlatTuple<T...>, I> {
- using value_type =
- typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
- T...>::type;
+ using value_type = typename ElemFromList<I, T...>::type;
FlatTupleElemBase() = default;
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
value_type value;
@@ -1192,12 +1194,12 @@ class FlatTuple
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
template <size_t I>
- const typename ElemFromList<I, Indices, T...>::type& Get() const {
+ const typename ElemFromList<I, T...>::type& Get() const {
return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
}
template <size_t I>
- typename ElemFromList<I, Indices, T...>::type& Get() {
+ typename ElemFromList<I, T...>::type& Get() {
return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
}
};
diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc
index 05ee1c7..8312bd1 100644
--- a/googletest/test/gtest_unittest.cc
+++ b/googletest/test/gtest_unittest.cc
@@ -7353,20 +7353,15 @@ TEST(IndexSequence, MakeIndexSequence) {
// ElemFromList
TEST(ElemFromList, Basic) {
using testing::internal::ElemFromList;
- using Idx = testing::internal::MakeIndexSequence<3>::type;
- EXPECT_TRUE((
- std::is_same<int, ElemFromList<0, Idx, int, double, char>::type>::value));
EXPECT_TRUE(
- (std::is_same<double,
- ElemFromList<1, Idx, int, double, char>::type>::value));
+ (std::is_same<int, ElemFromList<0, int, double, char>::type>::value));
EXPECT_TRUE(
- (std::is_same<char,
- ElemFromList<2, Idx, int, double, char>::type>::value));
+ (std::is_same<double, ElemFromList<1, int, double, char>::type>::value));
EXPECT_TRUE(
- (std::is_same<
- char, ElemFromList<7, testing::internal::MakeIndexSequence<12>::type,
- int, int, int, int, int, int, int, char, int, int,
- int, int>::type>::value));
+ (std::is_same<char, ElemFromList<2, int, double, char>::type>::value));
+ EXPECT_TRUE((
+ std::is_same<char, ElemFromList<7, int, int, int, int, int, int, int,
+ char, int, int, int, int>::type>::value));
}
// FlatTuple