From 2cf1f99b97e5a50b5d9db3d5450a6b474e36b79b Mon Sep 17 00:00:00 2001 From: ofats Date: Fri, 9 Oct 2020 12:24:56 -0400 Subject: Googletest export Add helper methos to internal FlatTuple. Refactor constructors. PiperOrigin-RevId: 336306681 --- googletest/include/gtest/internal/gtest-internal.h | 62 +++++++--- .../include/gtest/internal/gtest-param-util.h | 11 +- googletest/test/gtest_unittest.cc | 137 +++++++++++++++++++++ 3 files changed, 195 insertions(+), 15 deletions(-) diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index bd4e419..08a9f9b 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -1209,6 +1209,8 @@ struct ElemFromList { static_cast(nullptr)...)); }; +struct FlatTupleConstructTag {}; + template class FlatTuple; @@ -1219,7 +1221,9 @@ template struct FlatTupleElemBase, I> { using value_type = typename ElemFromList::type; FlatTupleElemBase() = default; - explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} + template + explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t) + : value(std::forward(t)) {} value_type value; }; @@ -1231,8 +1235,30 @@ struct FlatTupleBase, IndexSequence> : FlatTupleElemBase, Idx>... { using Indices = IndexSequence; FlatTupleBase() = default; - explicit FlatTupleBase(T... t) - : FlatTupleElemBase, Idx>(std::move(t))... {} + template + explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args) + : FlatTupleElemBase, Idx>(FlatTupleConstructTag{}, + std::forward(args))... {} + + template + const typename ElemFromList::type& Get() const { + return FlatTupleElemBase, I>::value; + } + + template + typename ElemFromList::type& Get() { + return FlatTupleElemBase, I>::value; + } + + template + auto Apply(F&& f) -> decltype(std::forward(f)(this->Get()...)) { + return std::forward(f)(Get()...); + } + + template + auto Apply(F&& f) const -> decltype(std::forward(f)(this->Get()...)) { + return std::forward(f)(Get()...); + } }; // 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 - const typename ElemFromList::type& Get() const { - return static_cast*>(this)->value; - } - - template - typename ElemFromList::type& Get() { - return static_cast*>(this)->value; - } + template ::type...)>::value && + (sizeof...(T) >= 1)>::type> + explicit FlatTuple(Args&&... args) + : FlatTuple::FlatTupleBase(FlatTupleConstructTag{}, + std::forward(args)...) {} + + 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 +struct tuple_size> + : std::integral_constant {}; + +} // namespace std + #define GTEST_MESSAGE_AT_(file, line, message, result_type) \ ::testing::internal::AssertHelper(result_type, file, line, message) \ = ::testing::Message() diff --git a/googletest/include/gtest/internal/gtest-param-util.h b/googletest/include/gtest/internal/gtest-param-util.h index f26d7d1..138d372 100644 --- a/googletest/include/gtest/internal/gtest-param-util.h +++ b/googletest/include/gtest/internal/gtest-param-util.h @@ -783,10 +783,15 @@ internal::ParamGenerator ValuesIn( namespace internal { // Used in the Values() function to provide polymorphic capabilities. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template class ValueArray { public: - ValueArray(Ts... v) : v_{std::move(v)...} {} + explicit ValueArray(Ts... v) : v_(std::move(v)...) {} template operator ParamGenerator() const { // NOLINT @@ -802,6 +807,10 @@ class ValueArray { FlatTuple v_; }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + template class CartesianProductGenerator : public ParamGeneratorInterface<::std::tuple> { diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 4995d07..aa4c21a 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -64,6 +64,7 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) { #include #include #include +#include #include #include #include @@ -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 tuple{5, "Hello"}; + + // Lambda. + EXPECT_TRUE(tuple.Apply([](int i, const std::string& s) -> bool { + return i == static_cast(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 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 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 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 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 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; -- cgit v0.12