//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef SMARTPTR_H #define SMARTPTR_H #ifdef _WIN32 #pragma once #endif class CRefCountAccessor { public: template< class T > static void AddRef( T *pObj ) { pObj->AddRef(); } template< class T > static void Release( T *pObj ) { pObj->Release(); } }; // This can be used if your objects use AddReference/ReleaseReference function names. class CRefCountAccessorLongName { public: template< class T > static void AddRef( T *pObj ) { pObj->AddReference(); } template< class T > static void Release( T *pObj ) { pObj->ReleaseReference(); } }; // // CPlainAutoPtr // is a smart wrapper for a pointer on the stack that performs "delete" upon destruction. // // No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used // for readability and ease of maintenance. // // Auto pointer supports an "arrow" operator for invoking methods on the pointee and a "dereference" operator // for getting a pointee reference. // // No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom" // if casting to bool or pointer happens to be useful). // // Test for validity with "IsValid", get the pointer with "Get". // template < typename T > class CPlainAutoPtr { public: explicit CPlainAutoPtr( T *p = NULL ) : m_p( p ) {} ~CPlainAutoPtr( void ) { Delete(); } public: void Delete( void ) { delete Detach(); } private: // Disallow copying, use Detach() instead to avoid ambiguity CPlainAutoPtr( CPlainAutoPtr const &x ); CPlainAutoPtr & operator = ( CPlainAutoPtr const &x ); public: void Attach( T *p ) { m_p = p; } T * Detach( void ) { T * p( m_p ); m_p = NULL; return p; } public: bool IsValid( void ) const { return m_p != NULL; } T * Get( void ) const { return m_p; } T * operator -> ( void ) const { return Get(); } T & operator * ( void ) const { return *Get(); } private: T * m_p; }; // // CArrayAutoPtr // is a smart wrapper for an array pointer on the stack that performs "delete []" upon destruction. // // No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used // for readability and ease of maintenance. // // Auto pointer supports an "indexing" operator for accessing array elements. // // No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom" // if casting to bool or pointer happens to be useful). // // Test for validity with "IsValid", get the array pointer with "Get". // template < typename T > class CArrayAutoPtr : public CPlainAutoPtr < T > // Warning: no polymorphic destructor (delete on base class will be a mistake) { public: explicit CArrayAutoPtr( T *p = NULL ) { this->Attach( p ); } ~CArrayAutoPtr( void ) { Delete(); } public: void Delete( void ) { delete [] this->Detach(); } public: T & operator [] ( int k ) const { return this->Get()[ k ]; } }; // Smart pointers can be used to automatically free an object when nobody points // at it anymore. Things contained in smart pointers must implement AddRef and Release // functions. If those functions are private, then the class must make // CRefCountAccessor a friend. template class CSmartPtr { public: CSmartPtr(); CSmartPtr( T *pObj ); CSmartPtr( const CSmartPtr &other ); ~CSmartPtr(); T* operator=( T *pObj ); void operator=( const CSmartPtr &other ); const T* operator->() const; T* operator->(); bool operator!() const; bool operator==( const T *pOther ) const; bool IsValid() const; // Tells if the pointer is valid. T* GetObject() const; // Get temporary object pointer, don't store it for later reuse! void MarkDeleted(); private: T *m_pObj; }; template< class T, class RefCountAccessor > inline CSmartPtr::CSmartPtr() { m_pObj = NULL; } template< class T, class RefCountAccessor > inline CSmartPtr::CSmartPtr( T *pObj ) { m_pObj = NULL; *this = pObj; } template< class T, class RefCountAccessor > inline CSmartPtr::CSmartPtr( const CSmartPtr &other ) { m_pObj = NULL; *this = other; } template< class T, class RefCountAccessor > inline CSmartPtr::~CSmartPtr() { if ( m_pObj ) { RefCountAccessor::Release( m_pObj ); } } template< class T, class RefCountAccessor > inline T* CSmartPtr::operator=( T *pObj ) { if ( pObj == m_pObj ) return pObj; if ( pObj ) { RefCountAccessor::AddRef( pObj ); } if ( m_pObj ) { RefCountAccessor::Release( m_pObj ); } m_pObj = pObj; return pObj; } template< class T, class RefCountAccessor > inline void CSmartPtr::MarkDeleted() { m_pObj = NULL; } template< class T, class RefCountAccessor > inline void CSmartPtr::operator=( const CSmartPtr &other ) { *this = other.m_pObj; } template< class T, class RefCountAccessor > inline const T* CSmartPtr::operator->() const { return m_pObj; } template< class T, class RefCountAccessor > inline T* CSmartPtr::operator->() { return m_pObj; } template< class T, class RefCountAccessor > inline bool CSmartPtr::operator!() const { return !m_pObj; } template< class T, class RefCountAccessor > inline bool CSmartPtr::operator==( const T *pOther ) const { return m_pObj == pOther; } template< class T, class RefCountAccessor > inline bool CSmartPtr::IsValid() const { return m_pObj != NULL; } template< class T, class RefCountAccessor > inline T* CSmartPtr::GetObject() const { return m_pObj; } // // CAutoPushPop // allows you to set value of a variable upon construction and destruction. // Constructors: // CAutoPushPop x( myvar ) // saves the value and restores upon destruction. // CAutoPushPop x( myvar, newvalue ) // saves the value, assigns new value upon construction, restores saved value upon destruction. // CAutoPushPop x( myvar, newvalue, restorevalue ) // assigns new value upon construction, assignes restorevalue upon destruction. // template < typename T > class CAutoPushPop { public: explicit CAutoPushPop( T& var ) : m_rVar( var ), m_valPop( var ) {} CAutoPushPop( T& var, T const &valPush ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; } CAutoPushPop( T& var, T const &valPush, T const &valPop ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; } ~CAutoPushPop() { m_rVar = m_valPop; } private: // forbid copying CAutoPushPop( CAutoPushPop const &x ); CAutoPushPop & operator = ( CAutoPushPop const &x ); public: T & Get() { return m_rVar; } private: T &m_rVar; T m_valPop; }; #endif // SMARTPTR_H