mercredi 18 août 2021

How to delete assign operator overloding from smart pointer .get()?

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?

  1. First Method
  • Removed_Type* Get() const;
  • And overload SharedPtr operator=(Removed_Type* _ptrRemoved);
  • But how to enable T* ptr = smart_pointer.Get() ?
  1. 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