#pragma once #include "EngineTypes.h" #include #include #include #include #define DEFINE_REF(x) \ typedef ::Seele::RefPtr P##x; \ typedef ::Seele::UniquePtr UP##x; \ typedef ::Seele::OwningPtr O##x; #define DECLARE_REF(x) \ class x; \ typedef ::Seele::RefPtr P##x; \ typedef ::Seele::UniquePtr UP##x; \ typedef ::Seele::OwningPtr O##x; #define DECLARE_NAME_REF(nmsp, x) \ namespace nmsp \ { \ class x; \ typedef RefPtr P##x; \ typedef UniquePtr UP##x; \ typedef OwningPtr O##x; \ } namespace Seele { template class RefPtr { public: constexpr RefPtr() noexcept : object(nullptr) { } constexpr RefPtr(std::nullptr_t) noexcept : object(nullptr) { } RefPtr(T* ptr) : object(ptr) { } constexpr RefPtr(const RefPtr& other) noexcept : object(other.object) { } constexpr RefPtr(RefPtr&& rhs) noexcept : object(std::move(rhs.object)) { rhs.object = nullptr; } template constexpr RefPtr cast() { T* t = object; F* f = dynamic_cast(t); if (f == nullptr) { return nullptr; } return RefPtr(f); } template constexpr const RefPtr cast() const { T* t = object; F* f = dynamic_cast(t); if (f == nullptr) { return nullptr; } return RefPtr(f); } constexpr RefPtr& operator=(const RefPtr& other) { if (this != &other) { object = other.object; } return *this; } constexpr RefPtr& operator=(RefPtr&& rhs) noexcept { if (this != &rhs) { object = std::move(rhs.object); rhs.object = nullptr; } return *this; } constexpr ~RefPtr() { } constexpr bool operator==(const RefPtr& rhs) const noexcept { return object == rhs.object; } constexpr auto operator<=>(const RefPtr& rhs) const noexcept { return object <=> rhs.object; } template constexpr operator RefPtr() { return RefPtr(static_cast(object)); } template constexpr operator RefPtr() const { return RefPtr(static_cast(object)); } constexpr T* operator->() { return object; } constexpr const T* operator->() const { return object; } constexpr T* getHandle() { return object; } constexpr const T* getHandle() const { return object; } private: T* object; }; template > class OwningPtr { public: OwningPtr() : pointer(nullptr) { } OwningPtr(T* ptr) : pointer(ptr) {} template OwningPtr(OwningPtr&& other) { pointer = dynamic_cast(*other); other.clear(); } OwningPtr(const OwningPtr& other) = delete; OwningPtr(OwningPtr&& other) noexcept { pointer = other.pointer; other.pointer = nullptr; } OwningPtr& operator=(const OwningPtr& other) = delete; OwningPtr& operator=(OwningPtr&& other) noexcept { if (this != &other) { if(pointer != nullptr) { Deleter()(pointer); } pointer = other.pointer; other.pointer = nullptr; } return *this; } ~OwningPtr() { Deleter()(pointer); } operator RefPtr() { return RefPtr(pointer); } operator RefPtr() const { return RefPtr(pointer); } constexpr T* operator->() { return pointer; } constexpr const T* operator->() const { return pointer; } constexpr T* operator*() { return pointer; } constexpr const T* operator*() const { return pointer; } constexpr bool operator==(std::nullptr_t) const noexcept { return pointer == nullptr; } constexpr auto operator<=>(const OwningPtr& rhs) const noexcept { return pointer <=> rhs.pointer; } // INTERNAL USE constexpr void clear() { pointer = nullptr; } private: friend class RefPtr; T* pointer; }; template class UniquePtr { public: UniquePtr() : handle(nullptr) { } UniquePtr(std::nullptr_t) : handle(nullptr) { } UniquePtr(T *ptr) : handle(ptr) { } UniquePtr(const UniquePtr &rhs) = delete; UniquePtr(UniquePtr &&rhs) noexcept : handle(rhs.handle) { rhs.handle = nullptr; } UniquePtr &operator=(const UniquePtr &rhs) = delete; UniquePtr &operator=(UniquePtr &&rhs) { if (this != &rhs) { handle = rhs.handle; rhs.handle = nullptr; } return *this; } ~UniquePtr() { delete handle; } inline bool operator==(const UniquePtr &other) const { return handle == other.handle; } inline bool operator!=(const UniquePtr &other) const { return handle != other.handle; } inline T *operator->() { return handle; } inline T* getHandle() { return handle; } bool isValid() { return handle != nullptr; } private: T *handle; }; } // namespace Seele