const RefPtr<T> now allows accessing T as non-const. Also add default hash function for RefPtr and UniqPtr based on the pointer value
88 lines
1.6 KiB
C++
88 lines
1.6 KiB
C++
#pragma once
|
|
|
|
#include <BAN/Errors.h>
|
|
#include <BAN/Hash.h>
|
|
#include <BAN/NoCopyMove.h>
|
|
|
|
namespace BAN
|
|
{
|
|
|
|
template<typename T>
|
|
class UniqPtr
|
|
{
|
|
BAN_NON_COPYABLE(UniqPtr);
|
|
|
|
public:
|
|
UniqPtr() = default;
|
|
|
|
template<typename U>
|
|
UniqPtr(UniqPtr<U>&& other)
|
|
{
|
|
m_pointer = other.m_pointer;
|
|
other.m_pointer = nullptr;
|
|
}
|
|
|
|
~UniqPtr()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
static UniqPtr adopt(T* pointer)
|
|
{
|
|
UniqPtr uniq;
|
|
uniq.m_pointer = pointer;
|
|
return uniq;
|
|
}
|
|
|
|
// NOTE: don't use is_constructible_v<T, Args...> as UniqPtr<T> is allowed with friends
|
|
template<typename... Args>
|
|
static BAN::ErrorOr<UniqPtr> create(Args&&... args) requires requires(Args&&... args) { T(forward<Args>(args)...); }
|
|
{
|
|
UniqPtr uniq;
|
|
uniq.m_pointer = new T(BAN::forward<Args>(args)...);
|
|
if (uniq.m_pointer == nullptr)
|
|
return BAN::Error::from_errno(ENOMEM);
|
|
return uniq;
|
|
}
|
|
|
|
template<typename U>
|
|
UniqPtr& operator=(UniqPtr<U>&& other)
|
|
{
|
|
clear();
|
|
m_pointer = other.m_pointer;
|
|
other.m_pointer = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
T* ptr() const { return m_pointer; }
|
|
T& operator*() const { ASSERT(!empty()); return *ptr(); }
|
|
T* operator->() const { ASSERT(!empty()); return ptr(); }
|
|
|
|
bool empty() const { return m_pointer == nullptr; }
|
|
explicit operator bool() const { return m_pointer; }
|
|
|
|
void clear()
|
|
{
|
|
if (m_pointer)
|
|
delete m_pointer;
|
|
m_pointer = nullptr;
|
|
}
|
|
|
|
private:
|
|
T* m_pointer = nullptr;
|
|
|
|
template<typename U>
|
|
friend class UniqPtr;
|
|
};
|
|
|
|
template<typename T>
|
|
struct hash<UniqPtr<T>>
|
|
{
|
|
constexpr hash_t operator()(const UniqPtr<T>& ptr) const
|
|
{
|
|
return hash<T*>()(ptr.ptr());
|
|
}
|
|
};
|
|
|
|
}
|