#pragma once
#include "base.hpp"
#include "type_traits.hpp"
NAMESPACE_SOUP
{
template <typename T, SOUP_RESTRICT(std::is_pointer_v<T>)>
class PointerAndBool
{
private:
uintptr_t data;
public:
PointerAndBool(T ptr)
: data(reinterpret_cast<uintptr_t>(ptr))
{
}
PointerAndBool(T ptr, bool b)
: data(reinterpret_cast<uintptr_t>(ptr))
{
data |= (uintptr_t)b;
}
[[nodiscard]] T getPointer() const noexcept
{
return reinterpret_cast<T>(data & ~(uintptr_t)1);
}
[[nodiscard]] bool getBool() const noexcept
{
return data & 1;
}
void setBool(bool b) noexcept
{
data &= ~static_cast<uintptr_t>(1);
data |= static_cast<uintptr_t>(b);
}
void set(T ptr, bool b)
{
data = reinterpret_cast<uintptr_t>(ptr);
data |= static_cast<uintptr_t>(b);
}
operator T() const noexcept
{
return getPointer();
}
[[nodiscard]] std::remove_pointer_t<T>& operator*() const noexcept
{
return *getPointer();
}
[[nodiscard]] T operator->() const noexcept
{
return getPointer();
}
[[nodiscard]] bool operator==(T b) const noexcept
{
return getPointer() == b;
}
[[nodiscard]] bool operator!=(T b) const noexcept
{
return !operator==(b);
}
};
}