diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index f07f58da..a8ab0942 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -1129,6 +1129,39 @@ struct Ignore { Ignore(...); // NOLINT }; +template +struct TypeWrapper { + using type = T; +}; + +template +struct IndexedConditionalRedundantType {}; + +template +struct IndexedConditionalRedundantType { + using type = void; +}; + +template +struct EnableIfAllImpl; + +template +struct EnableIfAllImpl, Cs...> + : TypeWrapper, IndexedConditionalRedundantType... {}; + +template +struct EnableIfAll + : EnableIfAllImpl::type, + Cs...> {}; + +template +struct EmptyListElem {}; + +template +struct ListElem { + using type = T; +}; + template struct ElemFromListImpl; template @@ -1151,35 +1184,57 @@ struct ElemFromList { template struct FlatTupleElem { T value; - FlatTupleElem() : value() {} + FlatTupleElem() noexcept(std::is_nothrow_constructible::value) : value() {} - template - explicit FlatTupleElem(Arg &&arg) : value(std::forward(arg)) {} + template ::value>::type> + explicit FlatTupleElem(Arg&& arg) : value(std::forward(arg)) {} }; template class FlatTupleBase; template -class FlatTupleBase, Ts...> - : FlatTupleElem... { +class FlatTupleBase, Ts...> : FlatTupleElem... { public: FlatTupleBase() {} - template + template ::value...>::type> explicit FlatTupleBase(Args&&... args) : FlatTupleElem(std::forward(args))... {} + template ::value...>::type> + explicit FlatTupleBase( + const FlatTupleBase, Args...>& args_tuple) + : FlatTupleElem(args_tuple.template Get())... {} + + template ::value...>::type> + explicit FlatTupleBase( + FlatTupleBase, Args...>&& args_tuple) + : FlatTupleElem(args_tuple.template Get())... {} + template const typename ElemFromList::type& Get() const { - return static_cast::type, I>*>(this)->value; + return static_cast< + const FlatTupleElem::type, I>*>( + this) + ->value; } template typename ElemFromList::type& Get() { - return static_cast::type, - I>*>(this)->value; + return static_cast< + FlatTupleElem::type, I>*>(this) + ->value; } }; @@ -1198,10 +1253,16 @@ struct FlatTuple : FlatTupleBase::type, Ts...> { FlatTuple() {} - template + template < + typename... Args, + typename = typename EnableIfAll< + void, std::is_constructible< + FlatTupleBase< + typename MakeIndexSequence::type, Ts...>, + Args&&...>::value>::type> explicit FlatTuple(Args&&... args) : FlatTupleBase::type, Ts...>( - std::forward(args)...){} + std::forward(args)...) {} }; // Utility functions to be called with static_assert to induce deprecation diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 8312bd10..c0578801 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -7368,6 +7368,9 @@ TEST(ElemFromList, Basic) { TEST(FlatTuple, Basic) { using testing::internal::FlatTuple; + EXPECT_TRUE(std::is_constructible>::value); + EXPECT_TRUE((std::is_constructible, FlatTuple<>>::value)); + FlatTuple tuple = {}; EXPECT_EQ(0, tuple.Get<0>()); EXPECT_EQ(0.0, tuple.Get<1>()); @@ -7378,6 +7381,16 @@ TEST(FlatTuple, Basic) { EXPECT_EQ(3.2, tuple.Get<1>()); EXPECT_EQ(std::string("Foo"), tuple.Get<2>()); + const FlatTuple copy_constructed_tuple(tuple); + EXPECT_EQ(7, copy_constructed_tuple.Get<0>()); + EXPECT_EQ(3.2, copy_constructed_tuple.Get<1>()); + EXPECT_EQ(std::string("Foo"), copy_constructed_tuple.Get<2>()); + + FlatTuple tuple_constructed_tuple(tuple); + EXPECT_EQ(7, tuple_constructed_tuple.Get<0>()); + EXPECT_EQ(3.2, tuple_constructed_tuple.Get<1>()); + EXPECT_EQ(std::string("Foo"), tuple_constructed_tuple.Get<2>()); + tuple.Get<1>() = 5.1; EXPECT_EQ(5.1, tuple.Get<1>()); }