I am implementing Smart Pointer, imitating std::shared_ptr
I did most of implementations of its functions. e.g.) No assign operator from raw pointer. bool operator overloading...
However, in details, shared_ptr allows us by following uses.
1) shared_ptr<A> pA(new A); // ok
2) shared_ptr<A> pA = new A; // ok (same with above case)
3) shared_ptr<A> pA = nullptr; // ok
4) shared_ptr<A> pA = make_shared<A>();
shared_ptr<A> pA2 = pA.get(); // prohibited
It seems .get() returns std::remove_extent_t* in STL lib. To implement such details, how can I design my SharedPtr functionalities?
- First Method
- Removed_Type* Get() const;
- And overload SharedPtr operator=(Removed_Type* _ptrRemoved);
- But how to enable T* ptr = smart_pointer.Get() ?
- Others
Here's my SharedPtr Code might help to understand my question.
#pragma once
#include "CriticalSection.h"
template<typename T>
class SharedPtr
{
template<typename S>
friend class SharedPtr;
private:
T* m_pRes;
UINT* m_iRefCount;
static CriticalSection m_tMutex;
private:
friend class Res;
friend class ResMgr;
SharedPtr(T* _pRes)
:
m_pRes(_pRes),
m_iRefCount(nullptr)
{
if (m_pRes)
{
m_iRefCount = new UINT(1);
}
}
public:
T* operator->()
{
assert(m_pRes && "[SharedPtr] Access Null Obj");
return m_pRes;
}
const T* operator->() const
{
assert(m_pRes && "[SharedPtr] Access Null Obj");
return m_pRes;
}
T* Get() { return m_pRes; }
const T* Get() const { return m_pRes; }
T** GetAddressOf() { return &m_pRes; }
T* const* GetAddressOf() const { return &m_pRes; }
UINT UseCount() const
{
if (m_iRefCount == nullptr)
return 0;
return m_iRefCount->load();
}
void Reset(T* _ptr = nullptr)
{
assert(_ptr != m_pRes);
if (m_pRes)
{
SubRef();
}
m_pRes = _ptr;
if (m_pRes)
{
assert(m_iRefCount == nullptr);
m_iRefCount = new UINT(1);
}
}
template<typename S>
SharedPtr<S> CastTo() const
{
assert(m_pRes != nullptr && dynamic_cast<S*>(m_pRes) != nullptr);
SharedPtr<S> pCast;
pCast.m_iRefCount = m_iRefCount;
pCast.m_pRes = (S*)m_pRes;
pCast.AddRef();
return pCast;
}
operator bool() const { return m_pRes != nullptr; }
bool operator==(nullptr_t) const { return m_pRes == nullptr; }
bool operator!=(nullptr_t) const { return m_pRes != nullptr; }
bool operator==(const SharedPtr<T>& rhs) const { return m_pRes == rhs.m_pRes; }
bool operator!=(const SharedPtr<T>& rhs) const { return m_pRes != rhs.m_pRes; }
private:
void AddRef()
{
m_tMutex.Lock();
++(*m_iRefCount);
m_tMutex.UnLock();
}
void SubRef()
{
m_tMutex.Lock();
--(*m_iRefCount);
if ((*m_iRefCount) == 0)
{
SAFE_DELETE(m_iRefCount);
SAFE_DELETE(m_pRes);
}
m_tMutex.UnLock();
}
public:
SharedPtr()
:
m_pRes(nullptr),
m_iRefCount(nullptr)
{}
~SharedPtr()
{
if (m_pRes)
{
SubRef();
}
}
SharedPtr(nullptr_t)
:
m_pRes(nullptr),
m_iRefCount(nullptr)
{}
SharedPtr& operator=(nullptr_t)
{
if (m_pRes)
{
SubRef();
}
m_pRes = nullptr;
m_iRefCount = nullptr;
return *this;
}
SharedPtr& operator=(T* _pRes) = delete;
SharedPtr(const SharedPtr<T>& rhs)
:
m_pRes(rhs.m_pRes),
m_iRefCount(rhs.m_iRefCount)
{
if (m_pRes)
{
AddRef();
}
}
SharedPtr& operator=(const SharedPtr<T>& _ptr)
{
if (m_pRes)
{
SubRef();
}
m_pRes = _ptr.m_pRes;
m_iRefCount = _ptr.m_iRefCount;
if (m_pRes)
{
AddRef();
}
return *this;
}
SharedPtr(SharedPtr<T>&& rhs) noexcept
:
m_pRes(rhs.m_pRes),
m_iRefCount(rhs.m_iRefCount)
{
rhs.m_pRes = nullptr;
rhs.m_iRefCount = nullptr;
}
SharedPtr& operator=(SharedPtr<T>&& _ptr) noexcept
{
if (m_pRes)
{
SubRef();
}
m_pRes = _ptr.m_pRes;
m_iRefCount = _ptr.m_iRefCount;
_ptr.m_iRefCount = nullptr;
_ptr.m_pRes = nullptr;
return *this;
}
};
template<typename T>
CriticalSection SharedPtr<T>::m_tMutex = {};
Aucun commentaire:
Enregistrer un commentaire