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