Googletest export

Add helper methos to internal FlatTuple. Refactor constructors.

PiperOrigin-RevId: 336306681
This commit is contained in:
ofats 2020-10-09 12:24:56 -04:00 committed by Derek Mauro
parent 0555b0eacb
commit 2cf1f99b97
3 changed files with 194 additions and 14 deletions

View File

@ -1209,6 +1209,8 @@ struct ElemFromList {
static_cast<T (*)()>(nullptr)...));
};
struct FlatTupleConstructTag {};
template <typename... T>
class FlatTuple;
@ -1219,7 +1221,9 @@ template <typename... T, size_t I>
struct FlatTupleElemBase<FlatTuple<T...>, I> {
using value_type = typename ElemFromList<I, T...>::type;
FlatTupleElemBase() = default;
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
template <typename Arg>
explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t)
: value(std::forward<Arg>(t)) {}
value_type value;
};
@ -1231,8 +1235,30 @@ struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
: FlatTupleElemBase<FlatTuple<T...>, Idx>... {
using Indices = IndexSequence<Idx...>;
FlatTupleBase() = default;
explicit FlatTupleBase(T... t)
: FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {}
template <typename... Args>
explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args)
: FlatTupleElemBase<FlatTuple<T...>, Idx>(FlatTupleConstructTag{},
std::forward<Args>(args))... {}
template <size_t I>
const typename ElemFromList<I, T...>::type& Get() const {
return FlatTupleElemBase<FlatTuple<T...>, I>::value;
}
template <size_t I>
typename ElemFromList<I, T...>::type& Get() {
return FlatTupleElemBase<FlatTuple<T...>, I>::value;
}
template <typename F>
auto Apply(F&& f) -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
return std::forward<F>(f)(Get<Idx>()...);
}
template <typename F>
auto Apply(F&& f) const -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) {
return std::forward<F>(f)(Get<Idx>()...);
}
};
// Analog to std::tuple but with different tradeoffs.
@ -1253,17 +1279,17 @@ class FlatTuple
public:
FlatTuple() = default;
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
template <typename... Args,
typename = typename std::enable_if<
!std::is_same<void(FlatTuple), void(typename std::decay<
Args>::type...)>::value &&
(sizeof...(T) >= 1)>::type>
explicit FlatTuple(Args&&... args)
: FlatTuple::FlatTupleBase(FlatTupleConstructTag{},
std::forward<Args>(args)...) {}
template <size_t I>
const typename ElemFromList<I, T...>::type& Get() const {
return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
}
template <size_t I>
typename ElemFromList<I, T...>::type& Get() {
return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
}
using FlatTuple::FlatTupleBase::Apply;
using FlatTuple::FlatTupleBase::Get;
};
// Utility functions to be called with static_assert to induce deprecation
@ -1296,6 +1322,14 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
} // namespace internal
} // namespace testing
namespace std {
template <typename... Ts>
struct tuple_size<testing::internal::FlatTuple<Ts...>>
: std::integral_constant<size_t, sizeof...(Ts)> {};
} // namespace std
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
::testing::internal::AssertHelper(result_type, file, line, message) \
= ::testing::Message()

View File

@ -783,10 +783,15 @@ internal::ParamGenerator<typename Container::value_type> ValuesIn(
namespace internal {
// Used in the Values() function to provide polymorphic capabilities.
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4100)
#endif
template <typename... Ts>
class ValueArray {
public:
ValueArray(Ts... v) : v_{std::move(v)...} {}
explicit ValueArray(Ts... v) : v_(std::move(v)...) {}
template <typename T>
operator ParamGenerator<T>() const { // NOLINT
@ -802,6 +807,10 @@ class ValueArray {
FlatTuple<Ts...> v_;
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
template <typename... T>
class CartesianProductGenerator
: public ParamGeneratorInterface<::std::tuple<T...>> {

View File

@ -64,6 +64,7 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
#include <cstdint>
#include <map>
#include <ostream>
#include <string>
#include <type_traits>
#include <unordered_set>
#include <vector>
@ -7533,6 +7534,142 @@ TEST(FlatTuple, Basic) {
EXPECT_EQ(5.1, tuple.Get<1>());
}
namespace {
std::string AddIntToString(int i, const std::string& s) {
return s + std::to_string(i);
}
} // namespace
TEST(FlatTuple, Apply) {
using testing::internal::FlatTuple;
FlatTuple<int, std::string> tuple{5, "Hello"};
// Lambda.
EXPECT_TRUE(tuple.Apply([](int i, const std::string& s) -> bool {
return i == static_cast<int>(s.size());
}));
// Function.
EXPECT_EQ(tuple.Apply(AddIntToString), "Hello5");
// Mutating operations.
tuple.Apply([](int& i, std::string& s) {
++i;
s += s;
});
EXPECT_EQ(tuple.Get<0>(), 6);
EXPECT_EQ(tuple.Get<1>(), "HelloHello");
}
struct ConstructionCounting {
ConstructionCounting() { ++default_ctor_calls; }
~ConstructionCounting() { ++dtor_calls; }
ConstructionCounting(const ConstructionCounting&) { ++copy_ctor_calls; }
ConstructionCounting(ConstructionCounting&&) noexcept { ++move_ctor_calls; }
ConstructionCounting& operator=(const ConstructionCounting&) {
++copy_assignment_calls;
return *this;
}
ConstructionCounting& operator=(ConstructionCounting&&) noexcept {
++move_assignment_calls;
return *this;
}
static void Reset() {
default_ctor_calls = 0;
dtor_calls = 0;
copy_ctor_calls = 0;
move_ctor_calls = 0;
copy_assignment_calls = 0;
move_assignment_calls = 0;
}
static int default_ctor_calls;
static int dtor_calls;
static int copy_ctor_calls;
static int move_ctor_calls;
static int copy_assignment_calls;
static int move_assignment_calls;
};
int ConstructionCounting::default_ctor_calls = 0;
int ConstructionCounting::dtor_calls = 0;
int ConstructionCounting::copy_ctor_calls = 0;
int ConstructionCounting::move_ctor_calls = 0;
int ConstructionCounting::copy_assignment_calls = 0;
int ConstructionCounting::move_assignment_calls = 0;
TEST(FlatTuple, ConstructorCalls) {
using testing::internal::FlatTuple;
// Default construction.
ConstructionCounting::Reset();
{ FlatTuple<ConstructionCounting> tuple; }
EXPECT_EQ(ConstructionCounting::default_ctor_calls, 1);
EXPECT_EQ(ConstructionCounting::dtor_calls, 1);
EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
// Copy construction.
ConstructionCounting::Reset();
{
ConstructionCounting elem;
FlatTuple<ConstructionCounting> tuple{elem};
}
EXPECT_EQ(ConstructionCounting::default_ctor_calls, 1);
EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 1);
EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
// Move construction.
ConstructionCounting::Reset();
{ FlatTuple<ConstructionCounting> tuple{ConstructionCounting{}}; }
EXPECT_EQ(ConstructionCounting::default_ctor_calls, 1);
EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::move_ctor_calls, 1);
EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
// Copy assignment.
// TODO(ofats): it should be testing assignment operator of FlatTuple, not its
// elements
ConstructionCounting::Reset();
{
FlatTuple<ConstructionCounting> tuple;
ConstructionCounting elem;
tuple.Get<0>() = elem;
}
EXPECT_EQ(ConstructionCounting::default_ctor_calls, 2);
EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 1);
EXPECT_EQ(ConstructionCounting::move_assignment_calls, 0);
// Move assignment.
// TODO(ofats): it should be testing assignment operator of FlatTuple, not its
// elements
ConstructionCounting::Reset();
{
FlatTuple<ConstructionCounting> tuple;
tuple.Get<0>() = ConstructionCounting{};
}
EXPECT_EQ(ConstructionCounting::default_ctor_calls, 2);
EXPECT_EQ(ConstructionCounting::dtor_calls, 2);
EXPECT_EQ(ConstructionCounting::copy_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::move_ctor_calls, 0);
EXPECT_EQ(ConstructionCounting::copy_assignment_calls, 0);
EXPECT_EQ(ConstructionCounting::move_assignment_calls, 1);
ConstructionCounting::Reset();
}
TEST(FlatTuple, ManyTypes) {
using testing::internal::FlatTuple;