[ox/std] Fix Optional

This commit is contained in:
Gary Talent 2023-02-06 22:43:30 -06:00
parent b064239ab1
commit 6769bb63d9

View File

@ -11,6 +11,7 @@
#include "bit.hpp" #include "bit.hpp"
#include "initializerlist.hpp" #include "initializerlist.hpp"
#include "iterator.hpp" #include "iterator.hpp"
#include "memory.hpp"
#include "new.hpp" #include "new.hpp"
#include "types.hpp" #include "types.hpp"
#include "utility.hpp" #include "utility.hpp"
@ -32,8 +33,6 @@ class Optional {
constexpr Optional(const Optional &other) { constexpr Optional(const Optional &other) {
if (other.m_ptr) { if (other.m_ptr) {
m_ptr = new(m_data) T(*other.m_ptr); m_ptr = new(m_data) T(*other.m_ptr);
} else {
m_ptr = nullptr;
} }
} }
@ -43,14 +42,12 @@ class Optional {
} }
if (other.m_ptr) { if (other.m_ptr) {
m_ptr = new(m_data) T(std::move(*other.m_ptr)); m_ptr = new(m_data) T(std::move(*other.m_ptr));
} else {
m_ptr = nullptr;
} }
} }
constexpr ~Optional() { constexpr ~Optional() {
if (m_ptr) { if (m_ptr) {
m_ptr->~T(); reset();
} }
} }
@ -98,8 +95,7 @@ class Optional {
} }
*m_ptr = *other.m_ptr; *m_ptr = *other.m_ptr;
} else if (m_ptr) { } else if (m_ptr) {
m_ptr->~T(); reset();
m_ptr = nullptr;
} }
return *this; return *this;
} }
@ -114,22 +110,29 @@ class Optional {
} }
*m_ptr = std::move(*other.m_ptr); *m_ptr = std::move(*other.m_ptr);
} else if (m_ptr) { } else if (m_ptr) {
m_ptr->~T(); reset();
m_ptr = nullptr;
} }
return *this; return *this;
} }
template<class... Args> template<class... Args>
constexpr T &emplace(Args &&...args) { constexpr T &emplace(Args &&...args) {
m_ptr = std::construct_at<T>(m_ptr, ox::forward<Args>(args)...); if (std::is_constant_evaluated()) {
m_ptr = new T(ox::forward<Args>(args)...);
} else {
m_ptr = std::construct_at<T>(reinterpret_cast<T*>(m_data), ox::forward<Args>(args)...);
}
return *m_ptr; return *m_ptr;
} }
template<typename U, class... Args> template<typename U, class... Args>
constexpr T &emplace_subclass(Args &&...args) { constexpr T &emplace_subclass(Args &&...args) {
static_assert(sizeof(U) <= buffSize, "Subclass is too large for this Optional"); static_assert(sizeof(U) <= buffSize, "Subclass is too large for this Optional");
m_ptr = std::construct_at<U>(m_ptr, ox::forward<Args>(args)...); if (std::is_constant_evaluated()) {
m_ptr = new U(ox::forward<Args>(args)...);
} else {
m_ptr = std::construct_at<U>(reinterpret_cast<T*>(m_data), ox::forward<Args>(args)...);
}
return *m_ptr; return *m_ptr;
} }
@ -143,7 +146,11 @@ class Optional {
} }
constexpr void reset() noexcept { constexpr void reset() noexcept {
if (std::is_constant_evaluated()) {
ox::safeDelete(m_ptr);
} else {
get()->~T(); get()->~T();
}
m_ptr = nullptr; m_ptr = nullptr;
} }