mirror of
https://github.com/google/googletest.git
synced 2024-12-27 10:11:03 +08:00
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
This commit is contained in:
parent
58c7197761
commit
ed78e54f38
@ -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, int, double, char>::type>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<double, ElemFromList<1, int, double, char>::type>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<char, ElemFromList<2, int, double, char>::type>::value));
|
||||
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));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<char,
|
||||
ElemFromList<2, Idx, 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<7, int, int, int, int, int, int, int,
|
||||
char, int, int, int, int>::type>::value));
|
||||
}
|
||||
|
||||
// FlatTuple
|
||||
|
Loading…
x
Reference in New Issue
Block a user