Commit f36d3331 by Abseil Team Committed by Copybara-Service

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
parent 1278ee9b
...@@ -89,9 +89,9 @@ struct Storage { ...@@ -89,9 +89,9 @@ struct Storage {
explicit constexpr Storage(absl::in_place_t, V&& v) explicit constexpr Storage(absl::in_place_t, V&& v)
: value(std::forward<V>(v)) {} : value(std::forward<V>(v)) {}
constexpr const T& get() const& { return value; } 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; } 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 <typename T, size_t I> template <typename T, size_t I>
...@@ -102,9 +102,9 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, true> : T { ...@@ -102,9 +102,9 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, true> : T {
explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward<V>(v)) {} explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward<V>(v)) {}
constexpr const T& get() const& { return *this; } 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); } constexpr const T&& get() const&& { return std::move(*this); }
T&& get() && { return std::move(*this); } constexpr T&& get() && { return std::move(*this); }
}; };
template <typename D, typename I, bool ShouldAnyUseBase> template <typename D, typename I, bool ShouldAnyUseBase>
...@@ -237,7 +237,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple ...@@ -237,7 +237,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
std::forward<Vs>(base)...) {} std::forward<Vs>(base)...) {}
template <int I> template <int I>
ElemT<I>& get() & { constexpr ElemT<I>& get() & {
return StorageT<I>::get(); return StorageT<I>::get();
} }
...@@ -247,7 +247,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple ...@@ -247,7 +247,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
} }
template <int I> template <int I>
ElemT<I>&& get() && { constexpr ElemT<I>&& get() && {
return std::move(*this).StorageT<I>::get(); return std::move(*this).StorageT<I>::get();
} }
......
...@@ -31,14 +31,22 @@ ...@@ -31,14 +31,22 @@
// These are declared at global scope purely so that error messages // These are declared at global scope purely so that error messages
// are smaller and easier to understand. // are smaller and easier to understand.
enum class CallType { kConstRef, kConstMove }; enum class CallType { kMutableRef, kConstRef, kMutableMove, kConstMove };
template <int> template <int>
struct Empty { struct Empty {
constexpr CallType value() & { return CallType::kMutableRef; }
constexpr CallType value() const& { return CallType::kConstRef; } constexpr CallType value() const& { return CallType::kConstRef; }
constexpr CallType value() && { return CallType::kMutableMove; }
constexpr CallType value() const&& { return CallType::kConstMove; } constexpr CallType value() const&& { return CallType::kConstMove; }
}; };
// Unconditionally return an lvalue reference to `t`.
template <typename T>
constexpr T& AsLValue(T&& t) {
return t;
}
template <typename T> template <typename T>
struct NotEmpty { struct NotEmpty {
T value; T value;
...@@ -375,8 +383,24 @@ TEST(CompressedTupleTest, Constexpr) { ...@@ -375,8 +383,24 @@ TEST(CompressedTupleTest, Constexpr) {
constexpr int value() const { return v; } constexpr int value() const { return v; }
int v; int v;
}; };
constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> x(
7, 1.25, CompressedTuple<int>(5), {}); using Tuple = CompressedTuple<int, double, CompressedTuple<int>, Empty<0>>;
constexpr int r0 =
AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<0>();
constexpr double r1 =
AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<1>();
constexpr int r2 =
AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<2>().get<0>();
constexpr CallType r3 =
AsLValue(Tuple(1, 0.75, CompressedTuple<int>(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<int>(5), {});
constexpr int x0 = x.get<0>(); constexpr int x0 = x.get<0>();
constexpr double x1 = x.get<1>(); constexpr double x1 = x.get<1>();
constexpr int x2 = x.get<2>().get<0>(); constexpr int x2 = x.get<2>().get<0>();
...@@ -387,6 +411,18 @@ TEST(CompressedTupleTest, Constexpr) { ...@@ -387,6 +411,18 @@ TEST(CompressedTupleTest, Constexpr) {
EXPECT_EQ(x2, 5); EXPECT_EQ(x2, 5);
EXPECT_EQ(x3, CallType::kConstRef); EXPECT_EQ(x3, CallType::kConstRef);
constexpr int m0 = Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<0>();
constexpr double m1 = Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<1>();
constexpr int m2 =
Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<2>().get<0>();
constexpr CallType m3 =
Tuple(5, 0.25, CompressedTuple<int>(3), {}).get<3>().value();
EXPECT_EQ(m0, 5);
EXPECT_EQ(m1, 0.25);
EXPECT_EQ(m2, 3);
EXPECT_EQ(m3, CallType::kMutableMove);
constexpr CompressedTuple<Empty<0>, TrivialStruct, int> trivial = {}; constexpr CompressedTuple<Empty<0>, TrivialStruct, int> trivial = {};
constexpr CallType trivial0 = trivial.get<0>().value(); constexpr CallType trivial0 = trivial.get<0>().value();
constexpr int trivial1 = trivial.get<1>().value(); constexpr int trivial1 = trivial.get<1>().value();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment