#pragma once #include "debug/debug.h" template class RefPtr; template RefPtr AdoptPtr(T* ptr); template RefPtr StaticCastRefPtr(const RefPtr& ref); template class RefPtr { public: RefPtr() : ptr_(nullptr) {} RefPtr(decltype(nullptr)) : ptr_(nullptr) {} RefPtr(const RefPtr& other) : ptr_(other.ptr_) { if (ptr_) { ptr_->Acquire(); } } RefPtr& operator=(const RefPtr& other) { T* old = ptr_; ptr_ = other.ptr_; if (ptr_) { ptr_->Acquire(); } if (old && old->Release()) { dbgln("Deleting obj %m", old); delete old; } return *this; } RefPtr(RefPtr&& other) : ptr_(other.ptr_) { other.ptr_ = nullptr; } RefPtr& operator=(RefPtr&& other) { // Swap T* ptr = ptr_; ptr_ = other.ptr_; other.ptr_ = ptr; return *this; } enum DontAdoptTag { DontAdopt, }; RefPtr(T* ptr, DontAdoptTag) : ptr_(ptr) { ptr->Acquire(); } T* get() const { return ptr_; }; T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } operator bool() const { return ptr_ != nullptr; } bool operator==(decltype(nullptr)) const { return (ptr_ == nullptr); } bool operator!=(decltype(nullptr)) const { return (ptr_ != nullptr); } bool operator==(const RefPtr& other) const { return (ptr_ == other.ptr_); } bool operator!=(const RefPtr& other) const { return (ptr_ != other.ptr_); } private: T* ptr_; friend RefPtr AdoptPtr(T* ptr); RefPtr(T* ptr) : ptr_(ptr) { ptr->Adopt(); } }; template class MakeRefCountedFriend final { public: template static RefPtr Make(Args&&... args) { return AdoptPtr(new T(args...)); } }; template RefPtr MakeRefCounted(Args&&... args) { return MakeRefCountedFriend::Make(args...); } template RefPtr AdoptPtr(T* ptr) { return RefPtr(ptr); } template RefPtr StaticCastRefPtr(const RefPtr& ref) { return RefPtr(static_cast(ref.get()), RefPtr::DontAdopt); }