diff options
-rw-r--r-- | AK/Optional.h | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/AK/Optional.h b/AK/Optional.h index 9af81ac13e..ee6320925e 100644 --- a/AK/Optional.h +++ b/AK/Optional.h @@ -1,12 +1,15 @@ #pragma once #include <AK/Assertions.h> +#include <AK/Platform.h> template<typename T> -class alignas(T) Optional { +class CONSUMABLE(unknown) alignas(T) Optional { public: + RETURN_TYPESTATE(unknown) Optional() {} + RETURN_TYPESTATE(unknown) Optional(T&& value) : m_has_value(true) { @@ -14,29 +17,33 @@ public: } template<typename U> + RETURN_TYPESTATE(unknown) Optional(U&& value) : m_has_value(true) { new (&m_storage) T(move(value)); } + RETURN_TYPESTATE(unknown) Optional(Optional&& other) : m_has_value(other.m_has_value) { if (m_has_value) { - new (&m_storage) T(move(other.value())); + new (&m_storage) T(move(other.value_without_consume_state())); other.m_has_value = false; } } + RETURN_TYPESTATE(unknown) Optional(const Optional& other) : m_has_value(other.m_has_value) { if (m_has_value) { - new (&m_storage) T(other.value()); + new (&m_storage) T(other.value_without_consume_state()); } } + RETURN_TYPESTATE(unknown) Optional& operator=(const Optional& other) { if (this != &other) { @@ -49,6 +56,7 @@ public: return *this; } + RETURN_TYPESTATE(unknown) Optional& operator=(Optional&& other) { if (this != &other) { @@ -74,20 +82,23 @@ public: } } + SET_TYPESTATE(consumed) bool has_value() const { return m_has_value; } + CALLABLE_WHEN(consumed) T& value() { ASSERT(m_has_value); return *reinterpret_cast<T*>(&m_storage); } + CALLABLE_WHEN(consumed) const T& value() const { - ASSERT(m_has_value); - return *reinterpret_cast<const T*>(&m_storage); + return value_without_consume_state(); } + CALLABLE_WHEN(consumed) T release_value() { ASSERT(m_has_value); @@ -98,14 +109,20 @@ public: T value_or(const T& fallback) const { - if (has_value()) + if (m_has_value) return value(); return fallback; } - operator bool() const { return has_value(); } + operator bool() const { return m_has_value; } private: + // Call when we don't want to alter the consume state + const T& value_without_consume_state() const + { + ASSERT(m_has_value); + return *reinterpret_cast<const T*>(&m_storage); + } char m_storage[sizeof(T)]; bool m_has_value { false }; }; |