90 lines
1.9 KiB
C++
90 lines
1.9 KiB
C++
#pragma once
|
|
|
|
namespace RE
|
|
{
|
|
template <class T, std::uintptr_t MASK = 1>
|
|
class BSTPointerAndFlags
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
using element_type = typename T::element_type;
|
|
|
|
constexpr BSTPointerAndFlags() noexcept = default;
|
|
|
|
BSTPointerAndFlags(const BSTPointerAndFlags& a_rhs) { _storage.ptr = a_rhs.get(); }
|
|
|
|
constexpr BSTPointerAndFlags(BSTPointerAndFlags&& a_rhs) noexcept
|
|
{
|
|
_storage.address = a_rhs._storage.address;
|
|
a_rhs._storage.address = 0;
|
|
}
|
|
|
|
constexpr BSTPointerAndFlags(std::nullptr_t) noexcept {}
|
|
|
|
~BSTPointerAndFlags()
|
|
{
|
|
clear_flags();
|
|
_storage.ptr.~value_type();
|
|
_storage.address = 0;
|
|
}
|
|
|
|
BSTPointerAndFlags& operator=(const BSTPointerAndFlags& a_rhs)
|
|
{
|
|
if (this != std::addressof(a_rhs)) {
|
|
clear_flags();
|
|
_storage.ptr = a_rhs.get();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
BSTPointerAndFlags& operator=(BSTPointerAndFlags&& a_rhs) noexcept
|
|
{
|
|
if (this != std::addressof(a_rhs)) {
|
|
clear_flags();
|
|
a_rhs.clear_flags();
|
|
_storage.address = a_rhs._storage.address;
|
|
a_rhs._storage.address = 0;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void reset() noexcept
|
|
{
|
|
clear_flags();
|
|
_storage.ptr.reset();
|
|
}
|
|
|
|
[[nodiscard]] element_type* get() const noexcept
|
|
{
|
|
auto ptr = _storage.address;
|
|
return reinterpret_cast<element_type*>(ptr & ~FLAG_MASK);
|
|
}
|
|
|
|
[[nodiscard]] element_type& operator*() const noexcept
|
|
{
|
|
assert(get() != nullptr);
|
|
return *get();
|
|
}
|
|
|
|
[[nodiscard]] element_type* operator->() const noexcept { return get(); }
|
|
|
|
[[nodiscard]] explicit operator bool() const noexcept { return get() != nullptr; }
|
|
|
|
protected:
|
|
union Storage
|
|
{
|
|
~Storage() noexcept {}
|
|
|
|
value_type ptr;
|
|
std::uintptr_t address{ 0 };
|
|
};
|
|
|
|
constexpr void clear_flags() noexcept { _storage.address &= ~FLAG_MASK; }
|
|
|
|
static constexpr std::uintptr_t FLAG_MASK = MASK;
|
|
|
|
// members
|
|
Storage _storage; // 0
|
|
};
|
|
}
|