I took the liberty of trying another approach.
I still get the pesky access errors, however. Don't know if it will yield more errors beyond what I get and if any linker errors.
Anyway, I did promise the code so you could see what's going on, so here it is:
Code:
#ifndef MAD_SHARED_PTR_175451_H
#define MAD_SHARED_PTR_175451_H
#ifndef NULL
#define NULL 0
#endif
const int nullptr = NULL;
//#include <boost/cstdint.hpp>
#include <memory>
#include <assert.h>
namespace boost
{
typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
}
class nullptr_t {};
template<typename T> T* mad_ptr_clone(const T* pOld) { return smad_ptr_int<T, boost::is_polymorphic<T>::value>::Clone(pOld); }
template<typename T, bool Polymorphic> struct smad_ptr_int
{
static T* Clone(const T* pOld) { return pOld->Clone(); } // IsPolymorphic = yes
};
template<typename T> struct smad_ptr_int<T, false>
{
static T* Clone(const T* pOld) { return new T(*pOld); } // IsPolymorphic = no
};
template<int N> struct ptr_bits { /*typedef current_amount_of_bits_not_supported rf_type;*/ };
template<> struct ptr_bits<32> { typedef boost::uint32_t rf_type; };
template<> struct ptr_bits<64> { typedef boost::uint64_t rf_type; };
#if _WIN32_WINNT >= 0x600 && WINVER >= 0x600
#include <windows.h>
template<int Bits> class ptr_thread_safe { };
template<> class ptr_thread_safe<32>
{
public:
static void Increment(void* p) { InterlockedIncrement((LONG*)p); }
static void Decrement(void* p) { InterlockedDecrement((LONG*)p); }
};
template<> class ptr_thread_safe<64>
{
public:
static void Increment(void* p) { InterlockedIncrement64((LONGLONG*)p); }
static void Decrement(void* p) { InterlockedDecrement64((LONGLONG*)p); }
};
#endif
template<int Bits> class ptr_thread_dangerous
{
public:
template<typename T> static void Increment(T* p) { (*p)++; }
template<typename T> static void Decrement(T* p) { (*p)--; }
};
class Derived;
template<typename T, int Bits> struct sptr;
template<typename T, int Bits, typename OtherT> sptr<T, Bits>* CastToSptrT(sptr<OtherT, Bits>* p)
{
T* pTest = p->p; // Test if Other is implicitly convertable to T.
return (sptr<T, Bits>*)p;
}
template<typename T, int Bits> struct sptr
{
template<typename T> class deleter_base { public: virtual void destroy(T* p) = 0; };
template<typename T, typename deleter_t> class deleter: public deleter_base<T>
{
public:
deleter(deleter_t delete_fnc): m_delete_fnc(delete_fnc) { }
virtual void destroy(T* p) { m_delete_fnc(p); }
private:
deleter_t m_delete_fnc;
};
sptr(): p(nullptr), RefCount(0), pDeleter(nullptr) { }
T* p;
typename ptr_bits<Bits>::rf_type RefCount;
deleter_base<T>* pDeleter;
template<typename T, int Bits, typename OtherT> friend sptr<T, Bits>* CastToSptrT <> (sptr<OtherT, Bits>* p);
};
//template<typename T, int Bits> class sptr_wrapper
//{
//public:
// sptr_wrapper(sptr<T, Bits>* p): m_p(p) {}
// template<typename OtherT> sptr_wrapper& operator = (const sptr_wrapper<OtherT, Bits>& rhs)
// {
// assert(m_p);
// assert(rhs.m_p);
// m_p->p = rhs.m_p->p;
// m_p->RefCount = rhs.m_p->RefCount;
// m_p->pDeleter = rhs.m_p->pDeleter;
// }
//
// sptr<T, Bits>* operator -> () { assert(m_p); return m_p; }
//
// sptr<T, Bits>* get() { assert(m_p); return m_p; }
// void set(sptr<T, Bits>* p) { assert(p); m_p = p; }
//
//protected:
// sptr<T, Bits>* m_p;
// template<typename T, int Bits> friend class sptr_wrapper;
//};
template<typename T, template<int> class thread_safety = ptr_thread_dangerous, int Bits = 32> class mad_shared_ptr
{
protected:
typedef void (mad_shared_ptr::* bool_type)() const;
typedef sptr<T, Bits> ptr_t;
public:
mad_shared_ptr(): m_ptr(nullptr) { }
template<typename Other> mad_shared_ptr(Other* p): m_ptr(nullptr) { *this = p; }
template<typename Other, typename Deleter> mad_shared_ptr(Other* p, Deleter delete_fnc): m_ptr(nullptr)
{
std::auto_ptr< ptr_t::deleter_base<T> > pDeleter( new ptr_t::deleter<T, Deleter>(delete_fnc) );
*this = p;
m_ptr->pDeleter = pDeleter.release();
}
mad_shared_ptr(const mad_shared_ptr& rhs): m_ptr(nullptr) { *this = rhs; }
template<typename Other> mad_shared_ptr(const mad_shared_ptr<Other>& rhs): m_ptr(nullptr) { *this = rhs; }
mad_shared_ptr(const nullptr_t&): m_ptr(nullptr) { }
~mad_shared_ptr() { DecRefCount(m_ptr); }
bool unique() const { return (m_ptr->RefCount == 1); }
void make_unique()
{
if (unique())
return;
std::auto_ptr<ptr_t> pNewPtr(new ptr_t);
pNewPtr->p = mad_ptr_clone(m_ptr->p);
pNewPtr->RefCount = 1;
pNewPtr->pDeleter = m_ptr->pDeleter;
DecRefCount(m_ptr);
m_ptr = pNewPtr.release();
}
void release()
{
DecRefCount();
m_p = nullptr;
m_RefCount = nullptr;
m_deleter = nullptr;
}
template<typename Other> mad_shared_ptr& operator = (Other* rhs)
{
if (m_ptr && rhs == m_ptr->p)
return *this;
ptr_t* pOldPtr = m_ptr;
std::auto_ptr<ptr_t> pNewPtr(new ptr_t);
pNewPtr->p = rhs;
pNewPtr->RefCount++;
m_ptr = pNewPtr.release();
DecRefCount(pOldPtr);
return *this;
}
mad_shared_ptr& operator = (const mad_shared_ptr& rhs)
{
return operator = <T>(rhs);
}
template<typename Other> mad_shared_ptr& operator = (const mad_shared_ptr<Other>& rhs)
{
if (rhs == *this)
return *this;
//T* pTest = rhs.m_ptr->p; // Test if Other is implicitly convertable to T.
DecRefCount(m_ptr);
m_ptr = CastToSptrT<T>(rhs.m_ptr);
IncRefCount(m_ptr);
return *this;
}
mad_shared_ptr& operator = (const nullptr_t&)
{
DecRefCount(m_ptr);
m_ptr = nullptr;
return *this;
}
T& operator * () const { assert(m_ptr); return *m_ptr->p; }
T* operator -> () const { assert(m_ptr); return m_ptr->p; }
template<typename rhs_t>
friend bool operator == (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
{
return (lhs.m_ptr == CastToSptrT<T>(rhs.m_ptr));
}
template<typename rhs_t>
friend bool operator != (const mad_shared_ptr& lhs, const mad_shared_ptr<rhs_t>& rhs)
{
return !(lhs == CastToSptrT(rhs));
}
operator bool_type() const
{
return m_ptr && m_ptr->p ? &mad_shared_ptr::this_type_does_not_support_comparisons : nullptr;
}
protected:
void IncRefCount(sptr<T, Bits>* ptr)
{
thread_safety<Bits>::Increment(&ptr->RefCount);
}
void DecRefCount(sptr<T, Bits>*& ptr)
{
if (ptr == nullptr)
return;
thread_safety<Bits>::Decrement(&ptr->RefCount);
if (ptr->RefCount == 0)
{
if (ptr->pDeleter)
ptr->pDeleter->destroy(ptr->p);
else
delete ptr->p;
delete ptr;
ptr = nullptr;
}
}
void this_type_does_not_support_comparisons() const {}
sptr<T, Bits>* m_ptr;
template<typename OtherT, template<int> class thread_safety, int Bits> friend class mad_shared_ptr;
};
#endif // MAD_SHARED_PTR_175451_H