From e76064e67fc3fd618345cd85f327b9bc49212709 Mon Sep 17 00:00:00 2001 From: Jonne Ransijn Date: Sun, 27 Oct 2024 10:13:43 +0100 Subject: [PATCH] AK: Allow `Optional` to be constructed from `Optional&` Attempting this resulted in an error because the `m_pointer` field does not exist on `Optional`. Creating a shared `ptr()` function and adding the necessairy overloads solves this issue. --- AK/Optional.h | 53 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/AK/Optional.h b/AK/Optional.h index 62b2a8303e2..658496fa319 100644 --- a/AK/Optional.h +++ b/AK/Optional.h @@ -202,6 +202,16 @@ public: [[nodiscard]] ALWAYS_INLINE bool has_value() const { return m_has_value; } + [[nodiscard]] ALWAYS_INLINE T* ptr() & + { + return m_has_value ? __builtin_launder(reinterpret_cast(&m_storage)) : nullptr; + } + + [[nodiscard]] ALWAYS_INLINE T const* ptr() const& + { + return m_has_value ? __builtin_launder(reinterpret_cast(&m_storage)) : nullptr; + } + [[nodiscard]] ALWAYS_INLINE T& value() & { VERIFY(m_has_value); @@ -362,20 +372,33 @@ public: } template - ALWAYS_INLINE Optional(Optional const& other) + ALWAYS_INLINE Optional(Optional& other) requires(CanBePlacedInOptional) - : m_pointer(other.m_pointer) + : m_pointer(other.ptr()) + { + } + + template + ALWAYS_INLINE Optional(Optional const& other) + requires(CanBePlacedInOptional) + : m_pointer(other.ptr()) { } template ALWAYS_INLINE Optional(Optional&& other) requires(CanBePlacedInOptional) - : m_pointer(other.m_pointer) + : m_pointer(other.ptr()) { other.m_pointer = nullptr; } + ALWAYS_INLINE Optional& operator=(Optional& other) + { + m_pointer = other.m_pointer; + return *this; + } + ALWAYS_INLINE Optional& operator=(Optional const& other) { m_pointer = other.m_pointer; @@ -390,16 +413,24 @@ public: } template - ALWAYS_INLINE Optional& operator=(Optional const& other) + ALWAYS_INLINE Optional& operator=(Optional& other) requires(CanBePlacedInOptional) { - m_pointer = other.m_pointer; + m_pointer = other.ptr(); + return *this; + } + + template + ALWAYS_INLINE Optional& operator=(Optional const& other) + requires(CanBePlacedInOptional) + { + m_pointer = other.ptr(); return *this; } template ALWAYS_INLINE Optional& operator=(Optional&& other) - requires(CanBePlacedInOptional) + requires(CanBePlacedInOptional && IsLvalueReference) { m_pointer = other.m_pointer; other.m_pointer = nullptr; @@ -423,6 +454,16 @@ public: [[nodiscard]] ALWAYS_INLINE bool has_value() const { return m_pointer != nullptr; } + [[nodiscard]] ALWAYS_INLINE RemoveReference* ptr() + { + return m_pointer; + } + + [[nodiscard]] ALWAYS_INLINE RemoveReference const* ptr() const + { + return m_pointer; + } + [[nodiscard]] ALWAYS_INLINE T value() { VERIFY(m_pointer);