#pragma once #include #include "RefCount.h" class EnableSharedFromThisBase; template class EnableSharedFromThis; class SharedPtrBase { public: void Reset() { if (_refCount != nullptr) { ResetIntern(); } } protected: void* _object; RefCount* _refCount; SharedPtrBase() : _object(nullptr), _refCount(nullptr) { } SharedPtrBase(void* object, RefCount* refCount) : _object(object), _refCount(refCount) { } SharedPtrBase(const void* object, RefCount* refCount) : _object((void*)object), _refCount(refCount) { } ~SharedPtrBase() { Reset(); } void ResetIntern(); }; template class SharedPtr : public SharedPtrBase { template friend class WeakPtr; template friend class SharedPtr; template friend class AtomicSharedPtr; template friend class EnableSharedFromThis; public: SharedPtr() { } SharedPtr(std::nullptr_t) { } explicit SharedPtr(T* object) : SharedPtrBase(object, object == nullptr ? nullptr : new StandaloneRefCount(object)) { if (_object != nullptr) { if constexpr (std::is_convertible::value) { _refCount->weakRefCount = 1; GetPointer()->__SetSharedFromThisWeakPtr(*this); } } } template requires std::assignable_from explicit SharedPtr(Y* object) : SharedPtrBase(static_cast(object), object == nullptr ? nullptr : new StandaloneRefCount(object)) { if (object != nullptr) { if constexpr (std::is_convertible::value) { _refCount->weakRefCount = 1; GetPointer()->__SetSharedFromThisWeakPtr(*this); } } } SharedPtr(const SharedPtr& other) : SharedPtrBase(other._object, other._refCount) { if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } } template requires std::assignable_from SharedPtr(const SharedPtr& other) : SharedPtrBase(static_cast(other.GetPointer()), other._refCount) { if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } } template explicit SharedPtr(const SharedPtr& other) : SharedPtrBase(static_cast(other.GetPointer()), other._refCount) { if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } } SharedPtr(SharedPtr&& other) : SharedPtrBase(other._object, other._refCount) { other._object = nullptr; other._refCount = nullptr; } template requires std::assignable_from SharedPtr(SharedPtr&& other) : SharedPtrBase(static_cast(other.GetPointer()), other._refCount) { other._object = nullptr; other._refCount = nullptr; } template explicit SharedPtr(SharedPtr&& other) : SharedPtrBase(static_cast(other.GetPointer()), other._refCount) { other._object = nullptr; other._refCount = nullptr; } static SharedPtr MakeShared(auto&&... args) { auto refCount = new MakeSharedRefCount(std::forward(args)...); return SharedPtr(refCount->GetObject(), refCount, true); } SharedPtr& operator=(const SharedPtr& other) { Reset(); _object = other._object; _refCount = other._refCount; if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } return *this; } template requires std::assignable_from SharedPtr& operator=(const SharedPtr& other) { Reset(); _object = static_cast(other.GetPointer()); _refCount = other._refCount; if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } return *this; } SharedPtr& operator=(SharedPtr&& other) { Reset(); _object = other._object; _refCount = other._refCount; other._object = nullptr; other._refCount = nullptr; return *this; } template requires std::assignable_from SharedPtr& operator=(SharedPtr&& other) { Reset(); _object = static_cast(other.GetPointer()); _refCount = other._refCount; other._object = nullptr; other._refCount = nullptr; return *this; } T& operator*() const { return *static_cast(_object); } T* operator->() const { return static_cast(_object); } T* GetPointer() const { return static_cast(_object); } bool IsValid() const { return _object != nullptr; } operator bool() const { return _object != nullptr; } private: SharedPtr(T* object, RefCount* refCount) : SharedPtrBase(object, refCount) { } SharedPtr(T* object, RefCount* refCount, bool doSharedFromThis) : SharedPtrBase(object, refCount) { if (doSharedFromThis) { if constexpr (std::is_convertible::value) { _refCount->weakRefCount = 1; GetPointer()->__SetSharedFromThisWeakPtr(*this); } } } };