Skip to content

Instantly share code, notes, and snippets.

@awesomekling
Created September 3, 2021 22:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save awesomekling/470cda90a8deaa9e639ebac3a7ba2dd9 to your computer and use it in GitHub Desktop.
Save awesomekling/470cda90a8deaa9e639ebac3a7ba2dd9 to your computer and use it in GitHub Desktop.
diff --git a/AK/Optional.h b/AK/Optional.h
index ff0745659..5265d3ce1 100644
--- a/AK/Optional.h
+++ b/AK/Optional.h
@@ -127,18 +127,28 @@ public:
[[nodiscard]] ALWAYS_INLINE bool has_value() const { return m_has_value; }
- [[nodiscard]] ALWAYS_INLINE T& value()
+ [[nodiscard]] ALWAYS_INLINE T& value() &
{
VERIFY(m_has_value);
return *__builtin_launder(reinterpret_cast<T*>(&m_storage));
}
- [[nodiscard]] ALWAYS_INLINE T const& value() const
+ [[nodiscard]] ALWAYS_INLINE T const& value() const &
{
VERIFY(m_has_value);
return *__builtin_launder(reinterpret_cast<T const*>(&m_storage));
}
+ [[nodiscard]] ALWAYS_INLINE T value() &&
+ {
+ VERIFY(m_has_value);
+ T& slot = *__builtin_launder(reinterpret_cast<T*>(&m_storage));
+ T released_value = move(slot);
+ slot.~T();
+ m_has_value = false;
+ return released_value;
+ }
+
[[nodiscard]] T release_value()
{
VERIFY(m_has_value);
@@ -148,13 +158,20 @@ public:
return released_value;
}
- [[nodiscard]] ALWAYS_INLINE T value_or(T const& fallback) const
+ [[nodiscard]] ALWAYS_INLINE T value_or(T const& fallback) const &
{
if (m_has_value)
return value();
return fallback;
}
+ [[nodiscard]] ALWAYS_INLINE T value_or(T&& fallback) &&
+ {
+ if (m_has_value)
+ return move(value());
+ return move(fallback);
+ }
+
ALWAYS_INLINE T const& operator*() const { return value(); }
ALWAYS_INLINE T& operator*() { return value(); }
diff --git a/Tests/AK/TestOptional.cpp b/Tests/AK/TestOptional.cpp
index 485a37f24..006fe2071 100644
--- a/Tests/AK/TestOptional.cpp
+++ b/Tests/AK/TestOptional.cpp
@@ -34,6 +34,27 @@ TEST_CASE(move_optional)
EXPECT_EQ(x.has_value(), false);
}
+TEST_CASE(optional_rvalue_ref_qualified_getters)
+{
+ struct DontCopyMe {
+ DontCopyMe() { }
+ ~DontCopyMe() = default;
+ DontCopyMe(DontCopyMe&&) = default;
+ DontCopyMe& operator=(DontCopyMe&&) = default;
+ DontCopyMe(DontCopyMe const&) = delete;
+ DontCopyMe& operator=(DontCopyMe const&) = delete;
+
+ int x { 13 };
+ };
+
+ auto make_an_optional = []() -> Optional<DontCopyMe> {
+ return DontCopyMe {};
+ };
+
+ EXPECT_EQ(make_an_optional().value().x, 13);
+ EXPECT_EQ(make_an_optional().value_or(DontCopyMe {}).x, 13);
+}
+
TEST_CASE(optional_leak_1)
{
struct Structure {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment