[llvm] 3c49576 - [ADT] Add has_value, value, value_or to llvm::Optional
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 18 21:21:39 PDT 2022
Author: Kazu Hirata
Date: 2022-06-18T21:21:33-07:00
New Revision: 3c49576417bab1b07764aa0b22664cbc8d3c3f53
URL: https://github.com/llvm/llvm-project/commit/3c49576417bab1b07764aa0b22664cbc8d3c3f53
DIFF: https://github.com/llvm/llvm-project/commit/3c49576417bab1b07764aa0b22664cbc8d3c3f53.diff
LOG: [ADT] Add has_value, value, value_or to llvm::Optional
This patch adds has_value, value, value_or to llvm::Optional so that
llvm::Optional looks more like std::optional.
I will keep the existing functions while migrating their callers and
then remove them later.
Differential Revision: https://reviews.llvm.org/D128131
Added:
Modified:
llvm/include/llvm/ADT/Optional.h
llvm/unittests/ADT/OptionalTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/Optional.h b/llvm/include/llvm/ADT/Optional.h
index 9570cfe4624d..b222339fd309 100644
--- a/llvm/include/llvm/ADT/Optional.h
+++ b/llvm/include/llvm/ADT/Optional.h
@@ -91,16 +91,29 @@ class OptionalStorage {
}
}
+ constexpr bool has_value() const noexcept { return hasVal; }
constexpr bool hasValue() const noexcept { return hasVal; }
+ T &value() &noexcept {
+ assert(hasVal);
+ return val;
+ }
T &getValue() &noexcept {
assert(hasVal);
return val;
}
+ constexpr T const &value() const &noexcept {
+ assert(hasVal);
+ return val;
+ }
constexpr T const &getValue() const &noexcept {
assert(hasVal);
return val;
}
+ T &&value() &&noexcept {
+ assert(hasVal);
+ return std::move(val);
+ }
T &&getValue() &&noexcept {
assert(hasVal);
return std::move(val);
@@ -189,16 +202,29 @@ template <typename T> class OptionalStorage<T, true> {
}
}
+ constexpr bool has_value() const noexcept { return hasVal; }
constexpr bool hasValue() const noexcept { return hasVal; }
+ T &value() &noexcept {
+ assert(hasVal);
+ return val;
+ }
T &getValue() &noexcept {
assert(hasVal);
return val;
}
+ constexpr T const &value() const &noexcept {
+ assert(hasVal);
+ return val;
+ }
constexpr T const &getValue() const &noexcept {
assert(hasVal);
return val;
}
+ T &&value() &&noexcept {
+ assert(hasVal);
+ return std::move(val);
+ }
T &&getValue() &&noexcept {
assert(hasVal);
return std::move(val);
@@ -276,16 +302,22 @@ template <typename T> class Optional {
constexpr const T *getPointer() const { return &Storage.getValue(); }
T *getPointer() { return &Storage.getValue(); }
+ constexpr const T &value() const & { return Storage.getValue(); }
constexpr const T &getValue() const & { return Storage.getValue(); }
+ T &value() & { return Storage.getValue(); }
T &getValue() & { return Storage.getValue(); }
constexpr explicit operator bool() const { return hasValue(); }
+ constexpr bool has_value() const { return Storage.hasValue(); }
constexpr bool hasValue() const { return Storage.hasValue(); }
constexpr const T *operator->() const { return getPointer(); }
T *operator->() { return getPointer(); }
constexpr const T &operator*() const & { return getValue(); }
T &operator*() & { return getValue(); }
+ template <typename U> constexpr T value_or(U &&value) const & {
+ return hasValue() ? getValue() : std::forward<U>(value);
+ }
template <typename U> constexpr T getValueOr(U &&value) const & {
return hasValue() ? getValue() : std::forward<U>(value);
}
@@ -298,9 +330,13 @@ template <typename T> class Optional {
return None;
}
+ T &&value() && { return std::move(Storage.getValue()); }
T &&getValue() && { return std::move(Storage.getValue()); }
T &&operator*() && { return std::move(Storage.getValue()); }
+ template <typename U> T value_or(U &&value) && {
+ return hasValue() ? std::move(getValue()) : std::forward<U>(value);
+ }
template <typename U> T getValueOr(U &&value) && {
return hasValue() ? std::move(getValue()) : std::forward<U>(value);
}
diff --git a/llvm/unittests/ADT/OptionalTest.cpp b/llvm/unittests/ADT/OptionalTest.cpp
index 06283f477e55..f88437f0ab29 100644
--- a/llvm/unittests/ADT/OptionalTest.cpp
+++ b/llvm/unittests/ADT/OptionalTest.cpp
@@ -27,10 +27,14 @@ static_assert(std::is_trivially_copyable<Optional<std::array<int, 3>>>::value,
void OptionalWorksInConstexpr() {
constexpr auto x1 = Optional<int>();
constexpr Optional<int> x2{};
+ static_assert(!x1.has_value() && !x2.has_value(),
+ "Default construction and hasValue() are contexpr");
static_assert(!x1.hasValue() && !x2.hasValue(),
"Default construction and hasValue() are contexpr");
constexpr auto y1 = Optional<int>(3);
constexpr Optional<int> y2{3};
+ static_assert(y1.value() == y2.value() && y1.value() == 3,
+ "Construction with value and getValue() are constexpr");
static_assert(y1.getValue() == y2.getValue() && y1.getValue() == 3,
"Construction with value and getValue() are constexpr");
static_assert(Optional<int>{3} >= 2 && Optional<int>{1} < Optional<int>{2},
@@ -205,9 +209,11 @@ TEST(OptionalTest, InPlaceConstructionNonDefaultConstructibleTest) {
TEST(OptionalTest, GetValueOr) {
Optional<int> A;
+ EXPECT_EQ(42, A.value_or(42));
EXPECT_EQ(42, A.getValueOr(42));
A = 5;
+ EXPECT_EQ(5, A.value_or(42));
EXPECT_EQ(5, A.getValueOr(42));
}
@@ -245,12 +251,14 @@ TEST(OptionalTest, Emplace) {
Optional<MultiArgConstructor> A;
A.emplace(1, 2);
+ EXPECT_TRUE(A.has_value());
EXPECT_TRUE(A.hasValue());
EXPECT_EQ(1, A->x);
EXPECT_EQ(2, A->y);
EXPECT_EQ(0u, MultiArgConstructor::Destructions);
A.emplace(5, false);
+ EXPECT_TRUE(A.has_value());
EXPECT_TRUE(A.hasValue());
EXPECT_EQ(5, A->x);
EXPECT_EQ(-5, A->y);
@@ -261,10 +269,12 @@ TEST(OptionalTest, InPlaceConstructionMultiArgConstructorTest) {
MultiArgConstructor::ResetCounts();
{
Optional<MultiArgConstructor> A{in_place, 1, 2};
+ EXPECT_TRUE(A.has_value());
EXPECT_TRUE(A.hasValue());
EXPECT_EQ(1, A->x);
EXPECT_EQ(2, A->y);
Optional<MultiArgConstructor> B{in_place, 5, false};
+ EXPECT_TRUE(B.has_value());
EXPECT_TRUE(B.hasValue());
EXPECT_EQ(5, B->x);
EXPECT_EQ(-5, B->y);
@@ -578,6 +588,23 @@ TEST(OptionalTest, DeletedCopyStringMap) {
Optional<NoCopyStringMap> TestInstantiation;
}
+TEST(OptionalTest, MoveValueOr) {
+ Optional<MoveOnly> A;
+
+ MoveOnly::ResetCounts();
+ EXPECT_EQ(42, std::move(A).value_or(MoveOnly(42)).val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(2u, MoveOnly::Destructions);
+
+ A = MoveOnly(5);
+ MoveOnly::ResetCounts();
+ EXPECT_EQ(5, std::move(A).value_or(MoveOnly(42)).val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(2u, MoveOnly::Destructions);
+}
+
TEST(OptionalTest, MoveGetValueOr) {
Optional<MoveOnly> A;
More information about the llvm-commits
mailing list