//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef SMARTPTR_H #define SMARTPTR_H #ifdef _WIN32 #pragma once #endif class CRefCountAccessor { public: template static void AddRef(T *pObj) { pObj->AddRef(); } template static void Release(T *pObj) { pObj->Release(); } }; // This can be used if your objects use AddReference/ReleaseReference function // names. class CRefCountAccessorLongName { public: template static void AddRef(T *pObj) { pObj->AddReference(); } template 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 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 class CArrayAutoPtr : public CPlainAutoPtr // Warning: no polymorphic destructor (delete on // base class will be a mistake) { public: explicit CArrayAutoPtr(T *p = NULL) { this->Attach(p); } ~CArrayAutoPtr(void) { this->Delete(); } public: void Delete(void) { delete[] CPlainAutoPtr::Detach(); } public: T &operator[](int k) const { return CPlainAutoPtr::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 inline CSmartPtr::CSmartPtr() { m_pObj = NULL; } template inline CSmartPtr::CSmartPtr(T *pObj) { m_pObj = NULL; *this = pObj; } template inline CSmartPtr::CSmartPtr( const CSmartPtr &other) { m_pObj = NULL; *this = other; } template inline CSmartPtr::~CSmartPtr() { if (m_pObj) { RefCountAccessor::Release(m_pObj); } } template 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 inline void CSmartPtr::MarkDeleted() { m_pObj = NULL; } template inline void CSmartPtr::operator=( const CSmartPtr &other) { *this = other.m_pObj; } template inline const T *CSmartPtr::operator->() const { return m_pObj; } template inline T *CSmartPtr::operator->() { return m_pObj; } template inline bool CSmartPtr::operator!() const { return !m_pObj; } template inline bool CSmartPtr::operator==(const T *pOther) const { return m_pObj == pOther; } template inline bool CSmartPtr::IsValid() const { return m_pObj != NULL; } template 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 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