BAN: Optional can now be constructed from another Optional

Also fix bug in release_value() where we did not call the
destructor.
This commit is contained in:
Bananymous 2023-10-11 19:39:10 +03:00
parent d4c9f371a6
commit 744ff40ba0
1 changed files with 42 additions and 26 deletions

View File

@ -13,6 +13,8 @@ namespace BAN
{ {
public: public:
Optional(); Optional();
Optional(Optional&&);
Optional(const Optional&);
Optional(const T&); Optional(const T&);
Optional(T&&); Optional(T&&);
template<typename... Args> template<typename... Args>
@ -20,8 +22,8 @@ namespace BAN
~Optional(); ~Optional();
Optional& operator=(const Optional&);
Optional& operator=(Optional&&); Optional& operator=(Optional&&);
Optional& operator=(const Optional&);
template<typename... Args> template<typename... Args>
Optional& emplace(Args&&...); Optional& emplace(Args&&...);
@ -34,9 +36,9 @@ namespace BAN
bool has_value() const; bool has_value() const;
T&& release_value(); T release_value();
const T& value() const;
T& value(); T& value();
const T& value() const;
void clear(); void clear();
@ -50,6 +52,22 @@ namespace BAN
: m_has_value(false) : m_has_value(false)
{} {}
template<typename T>
Optional<T>::Optional(Optional<T>&& other)
: m_has_value(other.has_value())
{
if (other.has_value())
new (m_storage) T(move(other.release_value()));
}
template<typename T>
Optional<T>::Optional(const Optional<T>& other)
: m_has_value(other.has_value())
{
if (other.has_value())
new (m_storage) T(other.value());
}
template<typename T> template<typename T>
Optional<T>::Optional(const T& value) Optional<T>::Optional(const T& value)
: m_has_value(true) : m_has_value(true)
@ -61,7 +79,7 @@ namespace BAN
Optional<T>::Optional(T&& value) Optional<T>::Optional(T&& value)
: m_has_value(true) : m_has_value(true)
{ {
new (m_storage) T(BAN::move(value)); new (m_storage) T(move(value));
} }
template<typename T> template<typename T>
@ -69,7 +87,7 @@ namespace BAN
Optional<T>::Optional(Args&&... args) Optional<T>::Optional(Args&&... args)
: m_has_value(true) : m_has_value(true)
{ {
new (m_storage) T(BAN::forward<Args>(args)...); new (m_storage) T(forward<Args>(args)...);
} }
template<typename T> template<typename T>
@ -79,26 +97,22 @@ namespace BAN
} }
template<typename T> template<typename T>
Optional<T>& Optional<T>::operator=(const Optional& other) Optional<T>& Optional<T>::operator=(Optional&& other)
{ {
clear(); clear();
m_has_value = other.has_value();
if (other.has_value()) if (other.has_value())
{ new (m_storage) T(move(other.release_value()));
m_has_value = true;
new (m_storage) T(other.value());
}
return *this; return *this;
} }
template<typename T> template<typename T>
Optional<T>& Optional<T>::operator=(Optional&& other) Optional<T>& Optional<T>::operator=(const Optional& other)
{ {
clear(); clear();
if (other.has_value()) m_has_value = other.has_value();
{ if (other.has_value)
m_has_value = true; new (m_storage) T(other.value());
new (m_storage) T(BAN::move(other.release_value()));
}
return *this; return *this;
} }
@ -108,7 +122,7 @@ namespace BAN
{ {
clear(); clear();
m_has_value = true; m_has_value = true;
new (m_storage) T(BAN::forward<Args>(args)...); new (m_storage) T(forward<Args>(args)...);
return *this; return *this;
} }
@ -147,18 +161,13 @@ namespace BAN
} }
template<typename T> template<typename T>
T&& Optional<T>::release_value() T Optional<T>::release_value()
{ {
ASSERT(has_value()); ASSERT(has_value());
T released_value = move(value());
value().~T();
m_has_value = false; m_has_value = false;
return BAN::move((T&)m_storage); return move(released_value);
}
template<typename T>
const T& Optional<T>::value() const
{
ASSERT(has_value());
return (const T&)m_storage;
} }
template<typename T> template<typename T>
@ -168,6 +177,13 @@ namespace BAN
return (T&)m_storage; return (T&)m_storage;
} }
template<typename T>
const T& Optional<T>::value() const
{
ASSERT(has_value());
return (const T&)m_storage;
}
template<typename T> template<typename T>
void Optional<T>::clear() void Optional<T>::clear()
{ {