summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--absl/container/internal/compressed_tuple.h12
-rw-r--r--absl/container/internal/compressed_tuple_test.cc42
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>(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 <typename T, size_t I>
@@ -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)) {}
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 <typename D, typename I, bool ShouldAnyUseBase>
@@ -237,7 +237,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
std::forward<Vs>(base)...) {}
template <int I>
- ElemT<I>& get() & {
+ constexpr ElemT<I>& get() & {
return StorageT<I>::get();
}
@@ -247,7 +247,7 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
}
template <int I>
- ElemT<I>&& get() && {
+ constexpr ElemT<I>&& get() && {
return std::move(*this).StorageT<I>::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 <int>
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 <typename T>
+constexpr T& AsLValue(T&& t) {
+ return t;
+}
+
template <typename T>
struct NotEmpty {
T value;
@@ -375,8 +383,24 @@ TEST(CompressedTupleTest, Constexpr) {
constexpr int value() const { return 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 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<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 CallType trivial0 = trivial.get<0>().value();
constexpr int trivial1 = trivial.get<1>().value();