mirror of
https://github.com/google/googletest.git
synced 2024-12-26 01:30:49 +08:00
[gtest] Use std::index_sequence
and friends instead of rolling our own
* Applies for `std::index_sequence`, `std::make_index_sequence`, and `std::index_sequence_for` replacing `IndexSequence`, `MakeIndexSequence` and IndexSequenceFor` * Also deleted implementation helper `DoubleSequence` * The standard interfaces [have been in the standard library since C++14](https://en.cppreference.com/w/cpp/utility/integer_sequence), which [is the minimum supported C++ version by Google Test](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md) PiperOrigin-RevId: 621939977 Change-Id: Id264266f08da66c0fa2a6e6fbb8f86fd3cb3a421
This commit is contained in:
parent
61db1e1740
commit
0af976647f
@ -2135,13 +2135,13 @@ struct ActionImpl<R(Args...), Impl> : ImplBase<Impl>::type {
|
||||
R operator()(Args&&... arg) const {
|
||||
static constexpr size_t kMaxArgs =
|
||||
sizeof...(Args) <= 10 ? sizeof...(Args) : 10;
|
||||
return Apply(MakeIndexSequence<kMaxArgs>{},
|
||||
MakeIndexSequence<10 - kMaxArgs>{},
|
||||
return Apply(std::make_index_sequence<kMaxArgs>{},
|
||||
std::make_index_sequence<10 - kMaxArgs>{},
|
||||
args_type{std::forward<Args>(arg)...});
|
||||
}
|
||||
|
||||
template <std::size_t... arg_id, std::size_t... excess_id>
|
||||
R Apply(IndexSequence<arg_id...>, IndexSequence<excess_id...>,
|
||||
R Apply(std::index_sequence<arg_id...>, std::index_sequence<excess_id...>,
|
||||
const args_type& args) const {
|
||||
// Impl need not be specific to the signature of action being implemented;
|
||||
// only the implementing function body needs to have all of the specific
|
||||
|
@ -490,12 +490,12 @@ class MatcherBaseImpl<Derived<Ts...>> {
|
||||
|
||||
template <typename F>
|
||||
operator ::testing::Matcher<F>() const { // NOLINT(runtime/explicit)
|
||||
return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{});
|
||||
return Apply<F>(std::make_index_sequence<sizeof...(Ts)>{});
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F, std::size_t... tuple_ids>
|
||||
::testing::Matcher<F> Apply(IndexSequence<tuple_ids...>) const {
|
||||
::testing::Matcher<F> Apply(std::index_sequence<tuple_ids...>) const {
|
||||
return ::testing::Matcher<F>(
|
||||
new typename Derived<Ts...>::template gmock_Impl<F>(
|
||||
std::get<tuple_ids>(params_)...));
|
||||
@ -3152,8 +3152,8 @@ class PairMatcher {
|
||||
};
|
||||
|
||||
template <typename T, size_t... I>
|
||||
auto UnpackStructImpl(const T& t, IndexSequence<I...>, int)
|
||||
-> decltype(std::tie(get<I>(t)...)) {
|
||||
auto UnpackStructImpl(const T& t, std::index_sequence<I...>,
|
||||
int) -> decltype(std::tie(get<I>(t)...)) {
|
||||
static_assert(std::tuple_size<T>::value == sizeof...(I),
|
||||
"Number of arguments doesn't match the number of fields.");
|
||||
return std::tie(get<I>(t)...);
|
||||
@ -3161,97 +3161,97 @@ auto UnpackStructImpl(const T& t, IndexSequence<I...>, int)
|
||||
|
||||
#if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<1>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<1>, char) {
|
||||
const auto& [a] = t;
|
||||
return std::tie(a);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<2>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<2>, char) {
|
||||
const auto& [a, b] = t;
|
||||
return std::tie(a, b);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<3>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<3>, char) {
|
||||
const auto& [a, b, c] = t;
|
||||
return std::tie(a, b, c);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<4>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<4>, char) {
|
||||
const auto& [a, b, c, d] = t;
|
||||
return std::tie(a, b, c, d);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<5>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<5>, char) {
|
||||
const auto& [a, b, c, d, e] = t;
|
||||
return std::tie(a, b, c, d, e);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<6>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<6>, char) {
|
||||
const auto& [a, b, c, d, e, f] = t;
|
||||
return std::tie(a, b, c, d, e, f);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<7>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<7>, char) {
|
||||
const auto& [a, b, c, d, e, f, g] = t;
|
||||
return std::tie(a, b, c, d, e, f, g);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<8>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<8>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<9>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<9>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<10>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<10>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<11>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<11>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<12>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<12>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<13>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<13>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<14>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<14>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<15>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<15>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<16>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<16>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<17>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<17>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<18>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<18>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r);
|
||||
}
|
||||
template <typename T>
|
||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<19>, char) {
|
||||
auto UnpackStructImpl(const T& t, std::make_index_sequence<19>, char) {
|
||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s] = t;
|
||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s);
|
||||
}
|
||||
@ -3259,8 +3259,8 @@ auto UnpackStructImpl(const T& t, MakeIndexSequence<19>, char) {
|
||||
|
||||
template <size_t I, typename T>
|
||||
auto UnpackStruct(const T& t)
|
||||
-> decltype((UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0)) {
|
||||
return (UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0);
|
||||
-> decltype((UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0)) {
|
||||
return (UnpackStructImpl)(t, std::make_index_sequence<I>{}, 0);
|
||||
}
|
||||
|
||||
// Helper function to do comma folding in C++11.
|
||||
@ -3273,7 +3273,7 @@ template <typename Struct, typename StructSize>
|
||||
class FieldsAreMatcherImpl;
|
||||
|
||||
template <typename Struct, size_t... I>
|
||||
class FieldsAreMatcherImpl<Struct, IndexSequence<I...>>
|
||||
class FieldsAreMatcherImpl<Struct, std::index_sequence<I...>>
|
||||
: public MatcherInterface<Struct> {
|
||||
using UnpackedType =
|
||||
decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>()));
|
||||
@ -3355,8 +3355,8 @@ class FieldsAreMatcher {
|
||||
template <typename Struct>
|
||||
operator Matcher<Struct>() const { // NOLINT
|
||||
return Matcher<Struct>(
|
||||
new FieldsAreMatcherImpl<const Struct&, IndexSequenceFor<Inner...>>(
|
||||
matchers_));
|
||||
new FieldsAreMatcherImpl<const Struct&,
|
||||
std::index_sequence_for<Inner...>>(matchers_));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/internal/gmock-port.h"
|
||||
@ -420,7 +421,7 @@ struct RemoveConstFromKey<std::pair<const K, V> > {
|
||||
GTEST_API_ void IllegalDoDefault(const char* file, int line);
|
||||
|
||||
template <typename F, typename Tuple, size_t... Idx>
|
||||
auto ApplyImpl(F&& f, Tuple&& args, IndexSequence<Idx...>)
|
||||
auto ApplyImpl(F&& f, Tuple&& args, std::index_sequence<Idx...>)
|
||||
-> decltype(std::forward<F>(f)(
|
||||
std::get<Idx>(std::forward<Tuple>(args))...)) {
|
||||
return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
|
||||
@ -428,12 +429,13 @@ auto ApplyImpl(F&& f, Tuple&& args, IndexSequence<Idx...>)
|
||||
|
||||
// Apply the function to a tuple of arguments.
|
||||
template <typename F, typename Tuple>
|
||||
auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl(
|
||||
std::forward<F>(f), std::forward<Tuple>(args),
|
||||
MakeIndexSequence<std::tuple_size<
|
||||
typename std::remove_reference<Tuple>::type>::value>())) {
|
||||
auto Apply(F&& f, Tuple&& args)
|
||||
-> decltype(ApplyImpl(
|
||||
std::forward<F>(f), std::forward<Tuple>(args),
|
||||
std::make_index_sequence<std::tuple_size<
|
||||
typename std::remove_reference<Tuple>::type>::value>())) {
|
||||
return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
|
||||
MakeIndexSequence<std::tuple_size<
|
||||
std::make_index_sequence<std::tuple_size<
|
||||
typename std::remove_reference<Tuple>::type>::value>());
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <iostream>
|
||||
#include <ostream> // NOLINT
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
@ -211,14 +212,14 @@ constexpr char UnBase64Impl(char c, const char* const base64, char carry) {
|
||||
}
|
||||
|
||||
template <size_t... I>
|
||||
constexpr std::array<char, 256> UnBase64Impl(IndexSequence<I...>,
|
||||
constexpr std::array<char, 256> UnBase64Impl(std::index_sequence<I...>,
|
||||
const char* const base64) {
|
||||
return {
|
||||
{UnBase64Impl(UndoWebSafeEncoding(static_cast<char>(I)), base64, 0)...}};
|
||||
}
|
||||
|
||||
constexpr std::array<char, 256> UnBase64(const char* const base64) {
|
||||
return UnBase64Impl(MakeIndexSequence<256>{}, base64);
|
||||
return UnBase64Impl(std::make_index_sequence<256>{}, base64);
|
||||
}
|
||||
|
||||
static constexpr char kBase64[] =
|
||||
|
@ -1137,40 +1137,6 @@ class NativeArray {
|
||||
void (NativeArray::*clone_)(const Element*, size_t);
|
||||
};
|
||||
|
||||
// Backport of std::index_sequence.
|
||||
template <size_t... Is>
|
||||
struct IndexSequence {
|
||||
using type = IndexSequence;
|
||||
};
|
||||
|
||||
// Double the IndexSequence, and one if plus_one is true.
|
||||
template <bool plus_one, typename T, size_t sizeofT>
|
||||
struct DoubleSequence;
|
||||
template <size_t... I, size_t sizeofT>
|
||||
struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
|
||||
using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
|
||||
};
|
||||
template <size_t... I, size_t sizeofT>
|
||||
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
|
||||
using type = IndexSequence<I..., (sizeofT + I)...>;
|
||||
};
|
||||
|
||||
// Backport of std::make_index_sequence.
|
||||
// It uses O(ln(N)) instantiation depth.
|
||||
template <size_t N>
|
||||
struct MakeIndexSequenceImpl
|
||||
: DoubleSequence<N % 2 == 1, typename MakeIndexSequenceImpl<N / 2>::type,
|
||||
N / 2>::type {};
|
||||
|
||||
template <>
|
||||
struct MakeIndexSequenceImpl<0> : IndexSequence<> {};
|
||||
|
||||
template <size_t N>
|
||||
using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::type;
|
||||
|
||||
template <typename... T>
|
||||
using IndexSequenceFor = typename MakeIndexSequence<sizeof...(T)>::type;
|
||||
|
||||
template <size_t>
|
||||
struct Ignore {
|
||||
Ignore(...); // NOLINT
|
||||
@ -1179,7 +1145,7 @@ struct Ignore {
|
||||
template <typename>
|
||||
struct ElemFromListImpl;
|
||||
template <size_t... I>
|
||||
struct ElemFromListImpl<IndexSequence<I...>> {
|
||||
struct ElemFromListImpl<std::index_sequence<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.
|
||||
@ -1190,9 +1156,8 @@ struct ElemFromListImpl<IndexSequence<I...>> {
|
||||
|
||||
template <size_t N, typename... T>
|
||||
struct ElemFromList {
|
||||
using type =
|
||||
decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply(
|
||||
static_cast<T (*)()>(nullptr)...));
|
||||
using type = decltype(ElemFromListImpl<std::make_index_sequence<N>>::Apply(
|
||||
static_cast<T (*)()>(nullptr)...));
|
||||
};
|
||||
|
||||
struct FlatTupleConstructTag {};
|
||||
@ -1217,9 +1182,9 @@ template <typename Derived, typename Idx>
|
||||
struct FlatTupleBase;
|
||||
|
||||
template <size_t... Idx, typename... T>
|
||||
struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
|
||||
struct FlatTupleBase<FlatTuple<T...>, std::index_sequence<Idx...>>
|
||||
: FlatTupleElemBase<FlatTuple<T...>, Idx>... {
|
||||
using Indices = IndexSequence<Idx...>;
|
||||
using Indices = std::index_sequence<Idx...>;
|
||||
FlatTupleBase() = default;
|
||||
template <typename... Args>
|
||||
explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
|
||||
@ -1254,14 +1219,15 @@ struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
|
||||
// implementations.
|
||||
// FlatTuple and ElemFromList are not recursive and have a fixed depth
|
||||
// regardless of T...
|
||||
// MakeIndexSequence, on the other hand, it is recursive but with an
|
||||
// std::make_index_sequence, on the other hand, it is recursive but with an
|
||||
// instantiation depth of O(ln(N)).
|
||||
template <typename... T>
|
||||
class FlatTuple
|
||||
: private FlatTupleBase<FlatTuple<T...>,
|
||||
typename MakeIndexSequence<sizeof...(T)>::type> {
|
||||
using Indices = typename FlatTupleBase<
|
||||
FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>::Indices;
|
||||
std::make_index_sequence<sizeof...(T)>> {
|
||||
using Indices =
|
||||
typename FlatTupleBase<FlatTuple<T...>,
|
||||
std::make_index_sequence<sizeof...(T)>>::Indices;
|
||||
|
||||
public:
|
||||
FlatTuple() = default;
|
||||
|
@ -807,12 +807,12 @@ class ValueArray {
|
||||
|
||||
template <typename T>
|
||||
operator ParamGenerator<T>() const { // NOLINT
|
||||
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
|
||||
return ValuesIn(MakeVector<T>(std::make_index_sequence<sizeof...(Ts)>()));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T, size_t... I>
|
||||
std::vector<T> MakeVector(IndexSequence<I...>) const {
|
||||
std::vector<T> MakeVector(std::index_sequence<I...>) const {
|
||||
return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
|
||||
}
|
||||
|
||||
@ -842,7 +842,7 @@ class CartesianProductGenerator
|
||||
template <class I>
|
||||
class IteratorImpl;
|
||||
template <size_t... I>
|
||||
class IteratorImpl<IndexSequence<I...>>
|
||||
class IteratorImpl<std::index_sequence<I...>>
|
||||
: public ParamIteratorInterface<ParamType> {
|
||||
public:
|
||||
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
|
||||
@ -933,7 +933,7 @@ class CartesianProductGenerator
|
||||
std::shared_ptr<ParamType> current_value_;
|
||||
};
|
||||
|
||||
using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
|
||||
using Iterator = IteratorImpl<std::make_index_sequence<sizeof...(T)>>;
|
||||
|
||||
std::tuple<ParamGenerator<T>...> generators_;
|
||||
};
|
||||
|
@ -7482,22 +7482,6 @@ TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
|
||||
EXPECT_EQ(a, na.begin());
|
||||
}
|
||||
|
||||
// IndexSequence
|
||||
TEST(IndexSequence, MakeIndexSequence) {
|
||||
using testing::internal::IndexSequence;
|
||||
using testing::internal::MakeIndexSequence;
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<IndexSequence<>, MakeIndexSequence<0>::type>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<IndexSequence<0>, MakeIndexSequence<1>::type>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<IndexSequence<0, 1>, MakeIndexSequence<2>::type>::value));
|
||||
EXPECT_TRUE((
|
||||
std::is_same<IndexSequence<0, 1, 2>, MakeIndexSequence<3>::type>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_base_of<IndexSequence<0, 1, 2>, MakeIndexSequence<3>>::value));
|
||||
}
|
||||
|
||||
// ElemFromList
|
||||
TEST(ElemFromList, Basic) {
|
||||
using testing::internal::ElemFromList;
|
||||
|
Loading…
x
Reference in New Issue
Block a user