#pragma once #include "types.h" #define SANITIZE_REFPTR template class RefPtr; template RefPtr adoptRef(T*); template class RefPtr { public: RefPtr() { } RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(m_ptr); } ~RefPtr() { derefIfNotNull(m_ptr); #ifdef SANITIZE_REFPTR m_ptr = (T*)(0xeeeeeeee); #endif } RefPtr(RefPtr&& other) : m_ptr(other.leakPtr()) { } RefPtr& operator=(RefPtr&& other) { if (this == &other) return *this; m_ptr = other.leakPtr(); return *this; } template RefPtr(RefPtr&& other) : m_ptr(static_cast(other.leakPtr())) { } template RefPtr& operator=(RefPtr&& other) { if (this == &other) return *this; m_ptr = static_cast(other.leakPtr()); return *this; } RefPtr(const RefPtr& other) : m_ptr(other.m_ptr) { refIfNotNull(m_ptr); } RefPtr& operator=(const RefPtr& other) { if (this == &other) return *this; m_ptr = other.m_ptr; refIfNotNull(m_ptr); return *this; } T* ptr() { return m_ptr; } const T* ptr() const { return m_ptr; } T* operator->() { return m_ptr; } const T* operator->() const { return m_ptr; } T& operator*() { return *m_ptr; } const T& operator*() const { return *m_ptr; } operator bool() const { return m_ptr; } T* leakPtr() { T* ptr = m_ptr; m_ptr = nullptr; return ptr; } private: template friend class RefPtr; friend RefPtr adoptRef(T*); enum AdoptTag { Adopt }; RefPtr(AdoptTag, T* ptr) : m_ptr(ptr) { } inline void refIfNotNull(T* ptr) { if (ptr) ptr->ref(); } inline void derefIfNotNull(T* ptr) { if (ptr) ptr->deref(); } T* m_ptr { nullptr }; }; template inline RefPtr adoptRef(T* ptr) { ASSERT(ptr->refCount() == 1); return RefPtr(RefPtr::Adopt, ptr); }