#pragma once #include "Macros.hpp" #include "TypeTraits.hpp" #include #include #include class RefCounted { public: // DO NOT MODIFY this field, unless explicitly documented the use size_t refCount = 0; }; template > class RcPtr : TDeleter { private: static_assert(std::is_base_of_v); T* mPtr; public: RcPtr() : mPtr{ nullptr } { } explicit RcPtr(T* ptr) : mPtr{ ptr } { if (ptr) { ++ptr->refCount; } } ~RcPtr() { CleanUp(); } void Attach(T* ptr) { CleanUp(); mPtr = ptr; if (ptr) { ++ptr->refCount; } } void Detatch() { CleanUp(); mPtr = nullptr; } RcPtr(const RcPtr& that) : mPtr{ that.mPtr } { if (mPtr) { ++mPtr->refCount; } } RcPtr& operator=(const RcPtr& that) { CleanUp(); mPtr = that.mPtr; if (mPtr) { ++mPtr->refCount; } return *this; } RcPtr(RcPtr&& that) : mPtr{ that.mPtr } { that.mPtr = nullptr; } RcPtr& operator=(RcPtr&& that) { CleanUp(); mPtr = that.mPtr; that.mPtr = nullptr; return *this; } template requires std::is_base_of_v operator RcPtr() const { return RcPtr(mPtr); } bool operator==(std::nullptr_t ptr) const { return mPtr == nullptr; } bool operator==(const T* ptr) const { return mPtr == ptr; } bool operator==(T* ptr) const { return mPtr == ptr; } T* Get() const { return mPtr; } T& operator*() const { return *mPtr; } T* operator->() const { return mPtr; } private: void CleanUp() { if (mPtr) { --mPtr->refCount; if (mPtr->refCount == 0) { TDeleter::operator()(mPtr); } } } };