1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004-2009
6 // License: BSD License, see ../docs/license.html
8 ////////////////////////////////////////////////////////////////////////////////
13 ////////////////////////////////////////////////////////////////////////////////
14 // internal holder data structure
15 ////////////////////////////////////////////////////////////////////////////////
18 class smart_ptr_holder
24 // make these private to disallow copying because the holder doesn't know how to copy
25 smart_ptr_holder(const smart_ptr_holder& s) :
30 smart_ptr_holder& operator=(const smart_ptr_holder& s)
36 smart_ptr_holder(T* p = 0) :
41 ~smart_ptr_holder(void)
46 unsigned count(void) const
85 const T* pointer(void) const
95 const T& value(void) const
101 ////////////////////////////////////////////////////////////////////////////////
102 // smart_ptr_base class
103 ////////////////////////////////////////////////////////////////////////////////
105 ////////////////////////////////////////////////////////////////////////////////
106 // constructors, assignments and destructors
108 // create a null pointer
109 template <typename T, typename C>
110 smart_ptr_base<T,C>::smart_ptr_base(void) :
111 m_holder(new smart_ptr_holder<T>)
115 // create a pointer containing a *copy* of the object pointer
116 template <typename T, typename C>
117 smart_ptr_base<T,C>::smart_ptr_base(const T& data) throw(illegal_copy) :
118 m_holder(new smart_ptr_holder<T>)
120 m_holder->set(C()(data));
123 // create a pointer containing a dynamically created object
124 // Note: the object must be allocated *by the user* with new
125 // constructor form - must be called in the form smart_ptr<type> x(new type(args))
126 template <typename T, typename C>
127 smart_ptr_base<T,C>::smart_ptr_base(T* data) :
128 m_holder(new smart_ptr_holder<T>)
133 // copy constructor implements counted referencing - no copy is made
134 template <typename T, typename C>
135 smart_ptr_base<T,C>::smart_ptr_base(const smart_ptr_base<T,C>& r) :
138 m_holder = r.m_holder;
139 m_holder->increment();
142 // destructor decrements the reference count and delete only when the last reference is destroyed
143 template <typename T, typename C>
144 smart_ptr_base<T,C>::~smart_ptr_base(void)
146 if(m_holder->decrement())
150 //////////////////////////////////////////////////////////////////////////////
151 // logical tests to see if there is anything contained in the pointer since it can be null
153 template <typename T, typename C>
154 bool smart_ptr_base<T,C>::null(void) const
156 return m_holder->null();
159 template <typename T, typename C>
160 bool smart_ptr_base<T,C>::present(void) const
162 return !m_holder->null();
165 template <typename T, typename C>
166 bool smart_ptr_base<T,C>::operator!(void) const
168 return m_holder->null();
171 template <typename T, typename C>
172 smart_ptr_base<T,C>::operator bool(void) const
174 return !m_holder->null();
177 //////////////////////////////////////////////////////////////////////////////
178 // dereference operators and functions
180 template <typename T, typename C>
181 T& smart_ptr_base<T,C>::operator*(void) throw(null_dereference)
183 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
184 return m_holder->value();
187 template <typename T, typename C>
188 const T& smart_ptr_base<T,C>::operator*(void) const throw(null_dereference)
190 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
191 return m_holder->value();
194 template <typename T, typename C>
195 T* smart_ptr_base<T,C>::operator->(void) throw(null_dereference)
197 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
198 return m_holder->pointer();
201 template <typename T, typename C>
202 const T* smart_ptr_base<T,C>::operator->(void) const throw(null_dereference)
204 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
205 return m_holder->pointer();
208 //////////////////////////////////////////////////////////////////////////////
209 // explicit function forms of the above assignment dereference operators
211 template <typename T, typename C>
212 void smart_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)
214 m_holder->set(C()(data));
217 template <typename T, typename C>
218 T& smart_ptr_base<T,C>::value(void) throw(null_dereference)
220 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
221 return m_holder->value();
224 template <typename T, typename C>
225 const T& smart_ptr_base<T,C>::value(void) const throw(null_dereference)
227 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
228 return m_holder->value();
231 template <typename T, typename C>
232 void smart_ptr_base<T,C>::set(T* data)
237 template <typename T, typename C>
238 T* smart_ptr_base<T,C>::pointer(void)
240 return m_holder->pointer();
243 template <typename T, typename C>
244 const T* smart_ptr_base<T,C>::pointer(void) const
246 return m_holder->pointer();
249 ////////////////////////////////////////////////////////////////////////////////
250 // functions to manage counted referencing
252 // make this an alias of the passed object
253 template <typename T, typename C>
254 void smart_ptr_base<T,C>::alias(const smart_ptr_base<T,C>& r)
256 // make it alias-copy safe - this means that I don't try to do the
257 // assignment if r is either the same object or an alias of it
258 // if (m_holder == r.m_holder) return;
259 // if (m_holder->decrement())
261 // m_holder = r.m_holder;
262 // m_holder->increment();
263 make_alias(r.m_holder);
266 template <typename T, typename C>
267 bool smart_ptr_base<T,C>::aliases(const smart_ptr_base<T,C>& r) const
269 return m_holder == r.m_holder;
272 template <typename T, typename C>
273 unsigned smart_ptr_base<T,C>::alias_count(void) const
275 return m_holder->count();
278 template <typename T, typename C>
279 void smart_ptr_base<T,C>::clear(void)
284 template <typename T, typename C>
285 void smart_ptr_base<T,C>::clear_unique(void)
287 if (m_holder->count() == 1)
291 m_holder->decrement();
293 m_holder = new smart_ptr_holder<T>;
297 template <typename T, typename C>
298 void smart_ptr_base<T,C>::make_unique(void) throw(illegal_copy)
300 if (m_holder->count() > 1)
302 smart_ptr_holder<T>* old_holder = m_holder;
303 m_holder->decrement();
305 m_holder = new smart_ptr_holder<T>;
306 if (old_holder->pointer())
307 m_holder->set(C()(old_holder->value()));
311 template <typename T, typename C>
312 void smart_ptr_base<T,C>::copy(const smart_ptr_base<T,C>& data) throw(illegal_copy)
318 // internal function for distinguishing unique smart_ptr objects
319 // used for example in persistence routines
321 template <typename T, typename C>
322 void* smart_ptr_base<T,C>::handle(void) const
327 template <typename T, typename C>
328 void smart_ptr_base<T,C>::make_alias(void* handle)
330 smart_ptr_holder<T>* r_holder = (smart_ptr_holder<T>*)handle;
331 if (m_holder != r_holder)
333 if (m_holder->decrement())
336 m_holder->increment();
340 ////////////////////////////////////////////////////////////////////////////////
342 } // end namespace stlplus