From f36d33317ce3ca0a2212ffd264a26fd18e57a509 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 1 Jul 2024 23:23:14 -0700 Subject: Make mutable CompressedTuple::get() constexpr. This change makes the mutable overloads of CompressedTuple::get() constexpr. This is consistent with std::get(std::tuple), which is constexpr since C++14. PiperOrigin-RevId: 648603141 Change-Id: Icbd61809f7a06723cf581dbed5488b7bae998cc9 --- absl/container/internal/compressed_tuple.h | 12 +++---- absl/container/internal/compressed_tuple_test.cc | 42 ++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h index f05a1fdc..6db0468d 100644 --- a/absl/container/internal/compressed_tuple.h +++ b/absl/container/internal/compressed_tuple.h @@ -89,9 +89,9 @@ struct Storage { explicit constexpr Storage(absl::in_place_t, V&& v) : value(std::forward(v)) {} constexpr const T& get() const& { return value; } - T& get() & { return value; } + constexpr T& get() & { return value; } constexpr const T&& get() const&& { return std::move(*this).value; } - T&& get() && { return std::move(*this).value; } + constexpr T&& get() && { return std::move(*this).value; } }; template @@ -102,9 +102,9 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage : T { explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward(v)) {} constexpr const T& get() const& { return *this; } - T& get() & { return *this; } + constexpr T& get() & { return *this; } constexpr const T&& get() const&& { return std::move(*this); } - T&& get() && { return std::move(*this); } + constexpr T&& get() && { return std::move(*this); } }; template @@ -237,7 +237,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple std::forward(base)...) {} template - ElemT& get() & { + constexpr ElemT& get() & { return StorageT::get(); } @@ -247,7 +247,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple } template - ElemT&& get() && { + constexpr ElemT&& get() && { return std::move(*this).StorageT::get(); } diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc index 3cd9e18b..c3edf542 100644 --- a/absl/container/internal/compressed_tuple_test.cc +++ b/absl/container/internal/compressed_tuple_test.cc @@ -31,14 +31,22 @@ // These are declared at global scope purely so that error messages // are smaller and easier to understand. -enum class CallType { kConstRef, kConstMove }; +enum class CallType { kMutableRef, kConstRef, kMutableMove, kConstMove }; template struct Empty { + constexpr CallType value() & { return CallType::kMutableRef; } constexpr CallType value() const& { return CallType::kConstRef; } + constexpr CallType value() && { return CallType::kMutableMove; } constexpr CallType value() const&& { return CallType::kConstMove; } }; +// Unconditionally return an lvalue reference to `t`. +template +constexpr T& AsLValue(T&& t) { + return t; +} + template struct NotEmpty { T value; @@ -375,8 +383,24 @@ TEST(CompressedTupleTest, Constexpr) { constexpr int value() const { return v; } int v; }; - constexpr CompressedTuple, Empty<0>> x( - 7, 1.25, CompressedTuple(5), {}); + + using Tuple = CompressedTuple, Empty<0>>; + + constexpr int r0 = + AsLValue(Tuple(1, 0.75, CompressedTuple(9), {})).get<0>(); + constexpr double r1 = + AsLValue(Tuple(1, 0.75, CompressedTuple(9), {})).get<1>(); + constexpr int r2 = + AsLValue(Tuple(1, 0.75, CompressedTuple(9), {})).get<2>().get<0>(); + constexpr CallType r3 = + AsLValue(Tuple(1, 0.75, CompressedTuple(9), {})).get<3>().value(); + + EXPECT_EQ(r0, 1); + EXPECT_EQ(r1, 0.75); + EXPECT_EQ(r2, 9); + EXPECT_EQ(r3, CallType::kMutableRef); + + constexpr Tuple x(7, 1.25, CompressedTuple(5), {}); constexpr int x0 = x.get<0>(); constexpr double x1 = x.get<1>(); constexpr int x2 = x.get<2>().get<0>(); @@ -387,6 +411,18 @@ TEST(CompressedTupleTest, Constexpr) { EXPECT_EQ(x2, 5); EXPECT_EQ(x3, CallType::kConstRef); + constexpr int m0 = Tuple(5, 0.25, CompressedTuple(3), {}).get<0>(); + constexpr double m1 = Tuple(5, 0.25, CompressedTuple(3), {}).get<1>(); + constexpr int m2 = + Tuple(5, 0.25, CompressedTuple(3), {}).get<2>().get<0>(); + constexpr CallType m3 = + Tuple(5, 0.25, CompressedTuple(3), {}).get<3>().value(); + + EXPECT_EQ(m0, 5); + EXPECT_EQ(m1, 0.25); + EXPECT_EQ(m2, 3); + EXPECT_EQ(m3, CallType::kMutableMove); + constexpr CompressedTuple, TrivialStruct, int> trivial = {}; constexpr CallType trivial0 = trivial.get<0>().value(); constexpr int trivial1 = trivial.get<1>().value(); -- cgit v1.2.3