#pragma once #ifndef Auto_Ptr_HPP #define Auto_Ptr_HPP #include "Stuff.hpp" namespace Stuff { // Auto_Ptr<>: similar to the STL auto_ptr<> class, but better! :) // An Auto_Ptr<> is a pointer that "owns" the object pointed to. // When the Auto_Ptr<> is deleted, it will also delete the object // if it still owns the pointer. Auto_Ptr<> also handles the transfer // of ownership between Auto_Ptrs via the == operators. // This version of Auto_Ptr<> is slightly more memory-efficient as it // stores the ownership bits in the unused bits of the pointer data member. // It also allows you to specify whether or not to use array deletion; // this also is stored in the extra bits of the pointer. template class Auto_Ptr { public: Auto_Ptr(); explicit Auto_Ptr(T* ptr, bool delete_as_array = DELETE_NORMAL); Auto_Ptr(Auto_Ptr const& src); ~Auto_Ptr(); enum deletion_type { DELETE_AS_ARRAY = true, DELETE_NORMAL = false }; Auto_Ptr Assimilate(T* ptr, bool delete_as_array = DELETE_NORMAL); Auto_Ptr Assimilate(Auto_Ptr& src); T* GetPointer() const; T* Release() const; T* ReleaseAndNull(); Auto_Ptr& operator=(Auto_Ptr const& src); operator bool() const; T& operator*() const; T* operator->() const; void Swap(Auto_Ptr& src); void Delete(); private: bool IsOwner() const; bool IsArray() const; void SetAsOwner(bool fOwn) const; void SetAsArray(bool fArray); void Set(T* ptr, bool fIsOwner, bool fIsArray); mutable union { T *m_ptr; mutable int unsigned m_bits; }; enum { OWNER_MASK = 1, ARRAY_MASK = 2, POINTER_MASK = ~3 }; }; template inline bool operator==(const Auto_Ptr& a, const Auto_Ptr& b) { return (a.GetPointer() == b.GetPointer()); } template inline bool operator==(const T* a, const Auto_Ptr& b) { return (a == b.GetPointer()); } template inline bool operator==(const Auto_Ptr& a, const T* b) { return (a.GetPointer() == b); } }; // namespace Stuff template Stuff::Auto_Ptr::Auto_Ptr() : m_ptr(0) { Verify(sizeof(T*) == sizeof(unsigned int)); } template Stuff::Auto_Ptr::Auto_Ptr(T* ptr, bool delete_as_array) { Verify(sizeof(T *) == sizeof(unsigned int)); Set(ptr,true,delete_as_array); } template Stuff::Auto_Ptr::Auto_Ptr(Auto_Ptr const& src) { Verify(sizeof(T*) == sizeof(unsigned int)); m_ptr = src.m_ptr; src.SetAsOwner(false); } template Stuff::Auto_Ptr::~Auto_Ptr() { Delete(); } template Stuff::Auto_Ptr Stuff::Auto_Ptr::Assimilate(T* ptr, bool delete_as_array) { Auto_Ptr temp(*this); Set(ptr,true,delete_as_array); return (temp); } template Stuff::Auto_Ptr Stuff::Auto_Ptr::Assimilate(Auto_Ptr& src) { Auto_Ptr temp; if (&src != this) { temp = *this; m_ptr = src.m_ptr; src.SetAsOwner(false); } return (temp); } template T* Stuff::Auto_Ptr::GetPointer() const { return ((T*)(m_bits & POINTER_MASK)); } template T* Stuff::Auto_Ptr::Release() const { SetAsOwner(false); return (GetPointer()); } template T* Stuff::Auto_Ptr::ReleaseAndNull() { T* rv = GetPointer(); m_ptr = 0; return (rv); } template Stuff::Auto_Ptr& Stuff::Auto_Ptr::operator=(Auto_Ptr const& src) { if (&src != this) { Delete(); m_ptr = src.m_ptr; src.SetAsOwner(false); } return (*this); } template Stuff::Auto_Ptr::operator bool() const { return (GetPointer() != 0); } template T& Stuff::Auto_Ptr::operator*() const { return (*GetPointer()); } template T* Stuff::Auto_Ptr::operator->() const { return (GetPointer()); } template void Stuff::Auto_Ptr::Swap(Auto_Ptr& src) { if (this != &src) { T* temp_ptr = src.m_ptr; src.m_ptr = m_ptr; m_ptr = temp_ptr; } } template void Stuff::Auto_Ptr::Delete() { if (IsOwner()) { if (IsArray()) { m_bits &= POINTER_MASK; delete [] m_ptr; } else { m_bits &= POINTER_MASK; delete m_ptr; } } m_ptr = 0; } template bool Stuff::Auto_Ptr::IsOwner() const { return ((m_bits & OWNER_MASK) == OWNER_MASK); } template bool Stuff::Auto_Ptr::IsArray() const { return ((m_bits & ARRAY_MASK) == ARRAY_MASK); } template void Stuff::Auto_Ptr::SetAsOwner(bool fOwn) const { if (fOwn == true) { m_bits |= OWNER_MASK; } else { m_bits &= ~OWNER_MASK; } } template void Stuff::Auto_Ptr::SetAsArray(bool fArray) { if (fArray == true) { m_bits |= ARRAY_MASK; } else { m_bits &= ~ARRAY_MASK; } } template void Stuff::Auto_Ptr::Set(T* ptr, bool fIsOwner, bool fIsArray) { m_ptr = ptr; Verify((m_bits & POINTER_MASK) == m_bits); if (fIsOwner == true) { m_bits |= OWNER_MASK; } if (fIsArray == true) { m_bits |= ARRAY_MASK; } } #endif // Auto_Ptr_HPP