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...)> {
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...);
......
......@@ -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;
}
};
......
......@@ -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
......
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