[ox/std] Make AnyPtr constexpr
All checks were successful
Build / build (push) Successful in 2m38s

This commit is contained in:
Gary Talent 2024-03-23 17:01:49 -05:00
parent 1616ca7018
commit 50f3479d10

View File

@ -9,9 +9,9 @@ namespace ox {
class AnyPtr { class AnyPtr {
private: private:
struct WrapBase { struct WrapBase {
virtual ~WrapBase() = default; virtual constexpr ~WrapBase() = default;
virtual WrapBase *copyTo(ox::Span<char> s) noexcept = 0; virtual constexpr WrapBase *copyTo(ox::Span<char> s) noexcept = 0;
virtual operator bool() const noexcept = 0; virtual constexpr operator bool() const noexcept = 0;
}; };
template<typename T> template<typename T>
@ -19,8 +19,12 @@ class AnyPtr {
T *data{}; T *data{};
constexpr Wrap(T *pData) noexcept: data(pData) { constexpr Wrap(T *pData) noexcept: data(pData) {
} }
inline WrapBase *copyTo(ox::Span<char> s) noexcept override { constexpr WrapBase *copyTo(ox::Span<char> s) noexcept override {
return new(s.data()) Wrap{data}; if (std::is_constant_evaluated()) {
return new Wrap(data);
} else {
return new(s.data()) Wrap(data);
}
} }
constexpr operator bool() const noexcept override { constexpr operator bool() const noexcept override {
return data != nullptr; return data != nullptr;
@ -29,25 +33,46 @@ class AnyPtr {
WrapBase *m_wrapPtr{}; WrapBase *m_wrapPtr{};
ox::Array<char, sizeof(Wrap<void*>)> m_wrapData; ox::Array<char, sizeof(Wrap<void*>)> m_wrapData;
public: public:
constexpr AnyPtr() noexcept = default; constexpr AnyPtr() noexcept = default;
template<typename T> template<typename T>
inline AnyPtr(T *ptr) noexcept { constexpr AnyPtr(T *ptr) noexcept {
if (std::is_constant_evaluated()) {
m_wrapPtr = new Wrap(ptr);
} else {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); m_wrapPtr = new(m_wrapData.data()) Wrap(ptr);
} }
inline AnyPtr(AnyPtr const&other) noexcept { }
constexpr AnyPtr(AnyPtr const&other) noexcept {
if (other) { if (other) {
m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData); m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData);
} }
} }
constexpr ~AnyPtr() noexcept {
if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr);
}
}
template<typename T> template<typename T>
inline AnyPtr &operator=(T *ptr) noexcept { constexpr AnyPtr &operator=(T *ptr) noexcept {
if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr);
m_wrapPtr = new Wrap(ptr);
} else {
m_wrapPtr = new(m_wrapData.data()) Wrap(ptr); m_wrapPtr = new(m_wrapData.data()) Wrap(ptr);
}
return *this; return *this;
} }
inline AnyPtr &operator=(AnyPtr const&ptr) noexcept {
constexpr AnyPtr &operator=(AnyPtr const&ptr) noexcept {
if (this != &ptr) { if (this != &ptr) {
if (ptr) { if (ptr) {
ox::safeDelete(m_wrapPtr);
m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData); m_wrapPtr = ptr.m_wrapPtr->copyTo(m_wrapData);
} else { } else {
m_wrapPtr = nullptr; m_wrapPtr = nullptr;
@ -55,18 +80,19 @@ class AnyPtr {
} }
return *this; return *this;
} }
constexpr operator bool() const noexcept { constexpr operator bool() const noexcept {
return m_wrapPtr && *m_wrapPtr; return m_wrapPtr && *m_wrapPtr;
} }
template<typename T> template<typename T>
[[nodiscard]] [[nodiscard]]
constexpr T *get() const noexcept { constexpr T *get() const noexcept {
#ifdef OX_BARE_METAL #ifdef OX_BARE_METAL
auto const out = static_cast<Wrap<T>*>(m_wrapPtr); return static_cast<Wrap<T>*>(m_wrapPtr)->data;
#else #else
auto const out = dynamic_cast<Wrap<T>*>(m_wrapPtr); return dynamic_cast<Wrap<T>*>(m_wrapPtr)->data;
#endif #endif
return out->data;
} }
}; };