diff options
author | Abseil Team <absl-team@google.com> | 2019-10-10 17:12:54 (GMT) |
---|---|---|
committer | Gennadiy Civil <misterg@google.com> | 2019-10-11 11:06:56 (GMT) |
commit | ed78e54f38ab10c775e39e5c4d500c6134a60d64 (patch) | |
tree | d911208bec3165eeaaf5a12f48181d25aa7be489 | |
parent | 58c71977611c0019cf077e43fb54bc3326409a43 (diff) | |
download | googletest-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.h | 3 | ||||
-rw-r--r-- | googletest/include/gtest/internal/gtest-internal.h | 44 | ||||
-rw-r--r-- | googletest/test/gtest_unittest.cc | 17 |
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 |