#pragma once #include #include #include namespace BAN { template class UniqPtr { BAN_NON_COPYABLE(UniqPtr); public: UniqPtr() = default; template UniqPtr(UniqPtr&& 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 as UniqPtr is allowed with friends template static BAN::ErrorOr create(Args&&... args) requires requires(Args&&... args) { T(forward(args)...); } { UniqPtr uniq; uniq.m_pointer = new T(BAN::forward(args)...); if (uniq.m_pointer == nullptr) return BAN::Error::from_errno(ENOMEM); return uniq; } template UniqPtr& operator=(UniqPtr&& 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 friend class UniqPtr; }; template struct hash> { constexpr hash_t operator()(const UniqPtr& ptr) const { return hash()(ptr.ptr()); } }; }