#pragma once #include "glacier/string/str_format.h" namespace glcr { 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_->AcquirePtr(); } } RefPtr& operator=(const RefPtr& other) { T* old = ptr_; ptr_ = other.ptr_; if (ptr_) { ptr_->AcquirePtr(); } if (old && old->ReleasePtr()) { 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->AcquirePtr(); } ~RefPtr() { if (ptr_) { if (ptr_->ReleasePtr()) { delete ptr_; } } } T* get() const { return ptr_; }; T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } bool empty() const { return ptr_ == nullptr; } 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->AdoptPtr(); } }; 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); } template void StrFormatValue(StringBuilder& builder, const RefPtr& value, StringView opts) { StrFormatValue(builder, (uint64_t)value.get(), opts); } } // namespace glcr