#ifndef _MEMORY_HPP__ #define _MEMORY_HPP__ namespace std { template <typename T, typename Enable = void> class cow_shared_ptr; class cow_shared_ptr_base { public: cow_shared_ptr_base() : m_UseCount(0) {} private: int m_UseCount; template<typename T, typename Enable> friend class cow_shared_ptr; }; template<class T> class cow_shared_ptr<T, typename std::enable_if< std::is_base_of<cow_shared_ptr_base, T>::value >::type> { public: cow_shared_ptr ( ) { attach ( NULL ); } cow_shared_ptr ( T * data ) { if(data) data->m_UseCount = 0; attach ( data ); } cow_shared_ptr ( const cow_shared_ptr<T> & other ) { attach ( other.m_Data ); } cow_shared_ptr ( cow_shared_ptr<T> && other ) noexcept { m_Data = other.m_Data; other.m_Data = NULL; } ~cow_shared_ptr ( ) noexcept { detach ( ); } cow_shared_ptr<T> & operator = ( const cow_shared_ptr<T> & other ) { if(this == &other) return *this; detach ( ); attach ( other.m_Data ); return *this; } cow_shared_ptr<T> & operator = ( cow_shared_ptr<T> && other ) noexcept { swap(*this, other); return *this; } T * operator -> ( ) { make_unique( ); return m_Data; } T const * operator -> ( ) const { return m_Data; } T & operator * ( ) { make_unique( ); return *m_Data; } T const & operator * ( ) const { return *m_Data; } T * get () { make_unique( ); return m_Data; } T const * get () const { return m_Data; } bool unique ( ) const { return m_Data == NULL || m_Data->m_UseCount == 1; } int getUseCount() const { if(m_Data == NULL) return 0; return m_Data->m_UseCount; } private: void attach ( T * data ) { m_Data = data; if(m_Data) m_Data->m_UseCount++; } void detach ( ) { if(m_Data && --(m_Data->m_UseCount) <= 0) delete m_Data; m_Data = NULL; } void make_unique( ) { if(unique( )) return; T* tmp = m_Data; detach( ); tmp = std::clone(tmp); tmp->m_UseCount = 0; attach(tmp); } T* m_Data; friend void swap ( cow_shared_ptr<T> & first, cow_shared_ptr<T> & second ) { T* tmp = first.m_Data; first.m_Data = second.m_Data; second.m_Data = tmp; } }; template<class T> class cow_shared_ptr<T, typename std::enable_if< ! std::is_base_of<cow_shared_ptr_base, T>::value >::type> { struct cow_shared_ptr_data { T * m_Data; int m_UseCount; cow_shared_ptr_data ( T * data ) : m_Data ( data ), m_UseCount( 0 ) { } ~cow_shared_ptr_data ( ) { delete m_Data; } }; public: cow_shared_ptr ( ) { attach ( NULL ); } cow_shared_ptr ( T * data ) { attach ( new cow_shared_ptr_data( data ) ); } cow_shared_ptr ( const cow_shared_ptr<T> & other ) { attach ( other.m_Data ); } cow_shared_ptr ( cow_shared_ptr<T> && other ) noexcept { m_Data = other.m_Data; other.m_Data = NULL; } ~cow_shared_ptr ( ) noexcept { detach ( ); } cow_shared_ptr<T> & operator = ( const cow_shared_ptr<T> & other ) { if(this == &other) return *this; detach ( ); attach ( other.m_Data ); return *this; } cow_shared_ptr<T> & operator = ( cow_shared_ptr<T> && other ) noexcept { swap(*this, other); return *this; } T * operator -> ( ) { make_unique( ); return m_Data->m_Data; } T const * operator -> ( ) const { return m_Data->m_Data; } T & operator * ( ) { make_unique( ); return *(m_Data->m_Data); } T const & operator * ( ) const { return *(m_Data->m_Data); } T * get () { make_unique( ); return m_Data->m_Data; } T const * get () const { return m_Data->m_Data; } bool unique ( ) const { return m_Data == NULL || m_Data->m_UseCount == 1; } private: void attach ( typename cow_shared_ptr<T>::cow_shared_ptr_data * data ) { m_Data = data; if(m_Data) m_Data->m_UseCount++; } void detach ( ) { if(m_Data && --(m_Data->m_UseCount) <= 0) delete m_Data; m_Data = NULL; } void make_unique( ) { if(unique( )) return; typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp = m_Data; detach( ); attach(new cow_shared_ptr_data(std::clone(tmp->m_Data))); } cow_shared_ptr_data * m_Data; friend void swap ( cow_shared_ptr<T> & first, cow_shared_ptr<T> & second ) { typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp = first.m_Data; first.m_Data = second.m_Data; second.m_Data = tmp; } }; template<class T> const cow_shared_ptr<T>& make_const(cow_shared_ptr<T>& ptr) { return static_cast<const cow_shared_ptr<T>&>(ptr); } template<class T> const cow_shared_ptr<T>& make_const(const cow_shared_ptr<T>& ptr) { return ptr; } } /* namespace std */ #endif // _MEMORY_HPP__