1 ///////////////////////////////////////////////////////////////////////////// 2 // Name: wx/scopedptr.h 3 // Purpose: scoped smart pointer class 4 // Author: Jesse Lovelace <jllovela@eos.ncsu.edu> 5 // Created: 06/01/02 6 // Copyright: (c) Jesse Lovelace and original Boost authors (see below) 7 // (c) 2009 Vadim Zeitlin 8 // Licence: wxWindows licence 9 ///////////////////////////////////////////////////////////////////////////// 10 11 // This class closely follows the implementation of the boost 12 // library scoped_ptr and is an adaption for c++ macro's in 13 // the wxWidgets project. The original authors of the boost 14 // scoped_ptr are given below with their respective copyrights. 15 16 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. 17 // Copyright (c) 2001, 2002 Peter Dimov 18 // 19 // Permission to copy, use, modify, sell and distribute this software 20 // is granted provided this copyright notice appears in all copies. 21 // This software is provided "as is" without express or implied 22 // warranty, and with no claim as to its suitability for any purpose. 23 // 24 // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. 25 // 26 27 #ifndef _WX_SCOPED_PTR_H_ 28 #define _WX_SCOPED_PTR_H_ 29 30 #include "wx/defs.h" 31 #include "wx/checkeddelete.h" 32 33 // ---------------------------------------------------------------------------- 34 // wxScopedPtr: A scoped pointer 35 // ---------------------------------------------------------------------------- 36 37 template <class T> 38 class wxScopedPtr 39 { 40 public: 41 typedef T element_type; 42 m_ptr(ptr)43 wxEXPLICIT wxScopedPtr(T * ptr = NULL) : m_ptr(ptr) { } 44 ~wxScopedPtr()45 ~wxScopedPtr() { wxCHECKED_DELETE(m_ptr); } 46 47 // test for pointer validity: defining conversion to unspecified_bool_type 48 // and not more obvious bool to avoid implicit conversions to integer types 49 #ifdef __BORLANDC__ 50 // this compiler is too dumb to use unspecified_bool_type operator in tests 51 // of the form "if ( !ptr )" 52 typedef bool unspecified_bool_type; 53 #else 54 typedef T *(wxScopedPtr<T>::*unspecified_bool_type)() const; 55 #endif // __BORLANDC__ unspecified_bool_type()56 operator unspecified_bool_type() const 57 { 58 return m_ptr ? &wxScopedPtr<T>::get : NULL; 59 } 60 61 void reset(T * ptr = NULL) 62 { 63 if ( ptr != m_ptr ) 64 { 65 wxCHECKED_DELETE(m_ptr); 66 m_ptr = ptr; 67 } 68 } 69 release()70 T *release() 71 { 72 T *ptr = m_ptr; 73 m_ptr = NULL; 74 return ptr; 75 } 76 77 T & operator*() const 78 { 79 wxASSERT(m_ptr != NULL); 80 return *m_ptr; 81 } 82 83 T * operator->() const 84 { 85 wxASSERT(m_ptr != NULL); 86 return m_ptr; 87 } 88 get()89 T * get() const 90 { 91 return m_ptr; 92 } 93 swap(wxScopedPtr & other)94 void swap(wxScopedPtr& other) 95 { 96 T * const tmp = other.m_ptr; 97 other.m_ptr = m_ptr; 98 m_ptr = tmp; 99 } 100 101 private: 102 T * m_ptr; 103 104 DECLARE_NO_COPY_TEMPLATE_CLASS(wxScopedPtr, T) 105 }; 106 107 // ---------------------------------------------------------------------------- 108 // old macro based implementation 109 // ---------------------------------------------------------------------------- 110 111 /* The type being used *must* be complete at the time 112 that wxDEFINE_SCOPED_* is called or a compiler error will result. 113 This is because the class checks for the completeness of the type 114 being used. */ 115 116 #define wxDECLARE_SCOPED_PTR(T, name) \ 117 class name \ 118 { \ 119 private: \ 120 T * m_ptr; \ 121 \ 122 name(name const &); \ 123 name & operator=(name const &); \ 124 \ 125 public: \ 126 wxEXPLICIT name(T * ptr = NULL) \ 127 : m_ptr(ptr) { } \ 128 \ 129 ~name(); \ 130 \ 131 void reset(T * ptr = NULL); \ 132 \ 133 T *release() \ 134 { \ 135 T *ptr = m_ptr; \ 136 m_ptr = NULL; \ 137 return ptr; \ 138 } \ 139 \ 140 T & operator*() const \ 141 { \ 142 wxASSERT(m_ptr != NULL); \ 143 return *m_ptr; \ 144 } \ 145 \ 146 T * operator->() const \ 147 { \ 148 wxASSERT(m_ptr != NULL); \ 149 return m_ptr; \ 150 } \ 151 \ 152 T * get() const \ 153 { \ 154 return m_ptr; \ 155 } \ 156 \ 157 void swap(name & ot) \ 158 { \ 159 T * tmp = ot.m_ptr; \ 160 ot.m_ptr = m_ptr; \ 161 m_ptr = tmp; \ 162 } \ 163 }; 164 165 #define wxDEFINE_SCOPED_PTR(T, name)\ 166 void name::reset(T * ptr) \ 167 { \ 168 if (m_ptr != ptr) \ 169 { \ 170 wxCHECKED_DELETE(m_ptr); \ 171 m_ptr = ptr; \ 172 } \ 173 } \ 174 name::~name() \ 175 { \ 176 wxCHECKED_DELETE(m_ptr); \ 177 } 178 179 // this macro can be used for the most common case when you want to declare and 180 // define the scoped pointer at the same time and want to use the standard 181 // naming convention: auto pointer to Foo is called FooPtr 182 #define wxDEFINE_SCOPED_PTR_TYPE(T) \ 183 wxDECLARE_SCOPED_PTR(T, T ## Ptr) \ 184 wxDEFINE_SCOPED_PTR(T, T ## Ptr) 185 186 // ---------------------------------------------------------------------------- 187 // "Tied" scoped pointer: same as normal one but also sets the value of 188 // some other variable to the pointer value 189 // ---------------------------------------------------------------------------- 190 191 #define wxDEFINE_TIED_SCOPED_PTR_TYPE(T) \ 192 wxDEFINE_SCOPED_PTR_TYPE(T) \ 193 class T ## TiedPtr : public T ## Ptr \ 194 { \ 195 public: \ 196 T ## TiedPtr(T **pp, T *p) \ 197 : T ## Ptr(p), m_pp(pp) \ 198 { \ 199 m_pOld = *pp; \ 200 *pp = p; \ 201 } \ 202 \ 203 ~ T ## TiedPtr() \ 204 { \ 205 *m_pp = m_pOld; \ 206 } \ 207 \ 208 private: \ 209 T **m_pp; \ 210 T *m_pOld; \ 211 }; 212 213 #endif // _WX_SCOPED_PTR_H_ 214 215