"...assets/git@developer.sourcefind.cn:yangql/googletest.git" did not exist on "d9c309fdab807b716c2cf4d4a42989b8c34f712a"
Commit ed78e54f authored by Abseil Team's avatar Abseil Team Committed by Gennadiy Civil
Browse files

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
parent 58c71977
...@@ -490,8 +490,7 @@ struct Function<R(Args...)> { ...@@ -490,8 +490,7 @@ struct Function<R(Args...)> {
using Result = R; using Result = R;
static constexpr size_t ArgumentCount = sizeof...(Args); static constexpr size_t ArgumentCount = sizeof...(Args);
template <size_t I> template <size_t I>
using Arg = ElemFromList<I, typename MakeIndexSequence<sizeof...(Args)>::type, using Arg = ElemFromList<I, Args...>;
Args...>;
using ArgumentTuple = std::tuple<Args...>; using ArgumentTuple = std::tuple<Args...>;
using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>; using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>;
using MakeResultVoid = void(Args...); using MakeResultVoid = void(Args...);
......
...@@ -1124,25 +1124,29 @@ struct MakeIndexSequence ...@@ -1124,25 +1124,29 @@ struct MakeIndexSequence
template <> template <>
struct MakeIndexSequence<0> : IndexSequence<> {}; struct MakeIndexSequence<0> : IndexSequence<> {};
// FIXME: This implementation of ElemFromList is O(1) in instantiation depth, template <size_t>
// but it is O(N^2) in total instantiations. Not sure if this is the best struct Ignore {
// tradeoff, as it will make it somewhat slow to compile. Ignore(...); // NOLINT
template <typename T, size_t, size_t>
struct ElemFromListImpl {};
template <typename T, size_t I>
struct ElemFromListImpl<T, I, I> {
using type = T;
}; };
// Get the Nth element from T... template <typename>
// It uses O(1) instantiation depth. struct ElemFromListImpl;
template <size_t N, typename I, typename... T> template <size_t... I>
struct ElemFromList; 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> template <size_t N, typename... T>
struct ElemFromList<N, IndexSequence<I...>, T...> struct ElemFromList {
: ElemFromListImpl<T, N, I>... {}; using type =
decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply(
static_cast<T (*)()>(nullptr)...));
};
template <typename... T> template <typename... T>
class FlatTuple; class FlatTuple;
...@@ -1152,9 +1156,7 @@ struct FlatTupleElemBase; ...@@ -1152,9 +1156,7 @@ struct FlatTupleElemBase;
template <typename... T, size_t I> template <typename... T, size_t I>
struct FlatTupleElemBase<FlatTuple<T...>, I> { struct FlatTupleElemBase<FlatTuple<T...>, I> {
using value_type = using value_type = typename ElemFromList<I, T...>::type;
typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
T...>::type;
FlatTupleElemBase() = default; FlatTupleElemBase() = default;
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
value_type value; value_type value;
...@@ -1192,12 +1194,12 @@ class FlatTuple ...@@ -1192,12 +1194,12 @@ class FlatTuple
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {} explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
template <size_t I> 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; return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
} }
template <size_t I> 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; return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
} }
}; };
......
...@@ -7353,20 +7353,15 @@ TEST(IndexSequence, MakeIndexSequence) { ...@@ -7353,20 +7353,15 @@ TEST(IndexSequence, MakeIndexSequence) {
// ElemFromList // ElemFromList
TEST(ElemFromList, Basic) { TEST(ElemFromList, Basic) {
using testing::internal::ElemFromList; 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( EXPECT_TRUE(
(std::is_same<double, (std::is_same<int, ElemFromList<0, int, double, char>::type>::value));
ElemFromList<1, Idx, int, double, char>::type>::value));
EXPECT_TRUE( EXPECT_TRUE(
(std::is_same<char, (std::is_same<double, ElemFromList<1, int, double, char>::type>::value));
ElemFromList<2, Idx, int, double, char>::type>::value));
EXPECT_TRUE( EXPECT_TRUE(
(std::is_same< (std::is_same<char, ElemFromList<2, int, double, char>::type>::value));
char, ElemFromList<7, testing::internal::MakeIndexSequence<12>::type, EXPECT_TRUE((
int, int, int, int, int, int, int, char, int, int, std::is_same<char, ElemFromList<7, int, int, int, int, int, int, int,
int, int>::type>::value)); char, int, int, int, int>::type>::value));
} }
// FlatTuple // FlatTuple
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment