1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Daniel Milton
4 // Copyright: (c) Daniel Milton 2002 onwards
6 ////////////////////////////////////////////////////////////////////////////////
11 ////////////////////////////////////////////////////////////////////////////////
12 // simple_ptr_base class
13 ////////////////////////////////////////////////////////////////////////////////
15 ////////////////////////////////////////////////////////////////////////////////
16 // constructors, assignments and destructors
18 // create a null pointer
19 template <typename T, typename C>
20 simple_ptr_base<T,C>::simple_ptr_base(void) :
22 m_count(new unsigned(1))
26 // create a pointer containing a *copy* of the object pointer
27 template <typename T, typename C>
28 simple_ptr_base<T,C>::simple_ptr_base(const T& data) throw(illegal_copy) :
30 m_count(new unsigned(1))
34 // create a pointer containing a dynamically created object
35 // Note: the object must be allocated *by the user* with new
36 // constructor form - must be called in the form simple_ptr<type> x(new type(args))
37 template <typename T, typename C>
38 simple_ptr_base<T,C>::simple_ptr_base(T* data) :
40 m_count(new unsigned(1))
44 // copy constructor implements counted referencing - no copy is made
45 template <typename T, typename C>
46 simple_ptr_base<T,C>::simple_ptr_base(const simple_ptr_base<T,C>& r) :
47 m_pointer(r.m_pointer),
53 // assignment operator - required, else the output of GCC suffers segmentation faults
54 template <typename T, typename C>
55 simple_ptr_base<T,C>& simple_ptr_base<T,C>::operator=(const simple_ptr_base<T,C>& r)
61 // destructor decrements the reference count and delete only when the last reference is destroyed
62 template <typename T, typename C>
63 simple_ptr_base<T,C>::~simple_ptr_base(void)
72 //////////////////////////////////////////////////////////////////////////////
73 // logical tests to see if there is anything contained in the pointer since it can be null
75 template <typename T, typename C>
76 bool simple_ptr_base<T,C>::null(void) const
81 template <typename T, typename C>
82 bool simple_ptr_base<T,C>::present(void) const
87 template <typename T, typename C>
88 bool simple_ptr_base<T,C>::operator!(void) const
93 template <typename T, typename C>
94 simple_ptr_base<T,C>::operator bool(void) const
99 //////////////////////////////////////////////////////////////////////////////
100 // dereference operators and functions
102 template <typename T, typename C>
103 T& simple_ptr_base<T,C>::operator*(void) throw(null_dereference)
105 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator*");
109 template <typename T, typename C>
110 const T& simple_ptr_base<T,C>::operator*(void) const throw(null_dereference)
112 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator*");
116 template <typename T, typename C>
117 T* simple_ptr_base<T,C>::operator->(void) throw(null_dereference)
119 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator->");
123 template <typename T, typename C>
124 const T* simple_ptr_base<T,C>::operator->(void) const throw(null_dereference)
126 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator->");
130 //////////////////////////////////////////////////////////////////////////////
131 // explicit function forms of the above assignment dereference operators
133 template <typename T, typename C>
134 void simple_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)
139 template <typename T, typename C>
140 T& simple_ptr_base<T,C>::value(void) throw(null_dereference)
142 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::value");
146 template <typename T, typename C>
147 const T& simple_ptr_base<T,C>::value(void) const throw(null_dereference)
149 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::value");
153 template <typename T, typename C>
154 void simple_ptr_base<T,C>::set(T* data)
156 unsigned& count = *m_count;
162 m_count = new unsigned(1);
167 template <typename T, typename C>
168 T* simple_ptr_base<T,C>::pointer(void)
173 template <typename T, typename C>
174 const T* simple_ptr_base<T,C>::pointer(void) const
179 ////////////////////////////////////////////////////////////////////////////////
180 // functions to manage counted referencing
182 template <typename T, typename C>
183 void simple_ptr_base<T,C>::increment(void)
188 template <typename T, typename C>
189 bool simple_ptr_base<T,C>::decrement(void)
191 unsigned& count = *m_count;
196 // make this an alias of the passed object
197 template <typename T, typename C>
198 void simple_ptr_base<T,C>::alias(const simple_ptr_base<T,C>& r)
200 // make it alias-copy safe - this means that I don't try to do the
201 // assignment if r is either the same object or an alias of it
202 if (m_pointer==r.m_pointer) return;
207 m_pointer = r.m_pointer;
212 template <typename T, typename C>
213 bool simple_ptr_base<T,C>::aliases(const simple_ptr_base<T,C>& r) const
215 return m_count == r.m_count;
218 template <typename T, typename C>
219 unsigned simple_ptr_base<T,C>::alias_count(void) const
224 template <typename T, typename C>
225 void simple_ptr_base<T,C>::clear(void)
230 template <typename T, typename C>
231 void simple_ptr_base<T,C>::clear_unique(void)
233 set(0); // no difference between clear and clear_unique with the simple_ptr
236 template <typename T, typename C>
237 void simple_ptr_base<T,C>::make_unique(void) throw(illegal_copy)
239 unsigned& count = *m_count;
240 if (count <= 1) return;
242 if (m_pointer) m_pointer = C()(*m_pointer);
243 m_count = new unsigned(1);
246 template <typename T, typename C>
247 void simple_ptr_base<T,C>::copy(const simple_ptr_base<T,C>& data) throw(illegal_copy)
253 // internal function for distinguishing unique simple_ptr objects
254 // used for example in persistence routines
256 template <typename T, typename C>
257 unsigned* simple_ptr_base<T,C>::_count(void) const
262 template <typename T, typename C>
263 T* simple_ptr_base<T,C>::_pointer(void) const
268 template <typename T, typename C>
269 void simple_ptr_base<T,C>::_make_alias(T* pointer, unsigned* count)
271 // make it alias-copy safe - this means that I don't try to do the
272 // assignment if r is either the same object or an alias of it
273 if (m_count != count)
287 ////////////////////////////////////////////////////////////////////////////////
289 ////////////////////////////////////////////////////////////////////////////////
291 #ifdef STLPLUS_MEMBER_TEMPLATES
293 template <typename T>
294 template <typename T2>
295 simple_ptr<T2> simple_ptr<T>::dyn_cast(void) const {
297 T2* p = dynamic_cast<T2*>(this->m_pointer);
298 if (p) rtn._make_alias(p, this->m_count);
302 template <typename T>
303 template <typename T2>
304 simple_ptr<T2> simple_ptr<T>::stat_cast(void) const {
306 T2* p = static_cast<T2*>(this->m_pointer);
307 if (p) rtn._make_alias(p, this->m_count);
311 template <typename T>
312 template <typename T2>
313 simple_ptr<T2> simple_ptr<T>::cast(void) const {
315 T2* p = (T2*)this->m_pointer;
316 if (p) rtn._make_alias(p, this->m_count);
322 ////////////////////////////////////////////////////////////////////////////////
323 // simple_ptr_clone class
324 ////////////////////////////////////////////////////////////////////////////////
326 #ifdef STLPLUS_MEMBER_TEMPLATES
328 template <typename T>
329 template <typename T2>
330 simple_ptr_clone<T2> simple_ptr_clone<T>::dyn_cast(void) const {
331 simple_ptr_clone<T2> rtn;
332 T2* p = dynamic_cast<T2*>(this->m_pointer);
333 if (p) rtn._make_alias(p, this->m_count);
337 template <typename T>
338 template <typename T2>
339 simple_ptr_clone<T2> simple_ptr_clone<T>::stat_cast(void) const {
340 simple_ptr_clone<T2> rtn;
341 T2* p = static_cast<T2*>(this->m_pointer);
342 if (p) rtn._make_alias(p, this->m_count);
346 template <typename T>
347 template <typename T2>
348 simple_ptr_clone<T2> simple_ptr_clone<T>::cast(void) const {
349 simple_ptr_clone<T2> rtn;
350 T2* p = (T2*)this->m_pointer;
351 if (p) rtn._make_alias(p, this->m_count);
357 ////////////////////////////////////////////////////////////////////////////////
358 // simple_ptr_nocopy class
359 ////////////////////////////////////////////////////////////////////////////////
361 #ifdef STLPLUS_MEMBER_TEMPLATES
363 template <typename T>
364 template <typename T2>
365 simple_ptr_nocopy<T2> simple_ptr_nocopy<T>::dyn_cast(void) const {
366 simple_ptr_nocopy<T2> rtn;
367 T2* p = dynamic_cast<T2*>(this->m_pointer);
368 if (p) rtn._make_alias(p, this->m_count);
372 template <typename T>
373 template <typename T2>
374 simple_ptr_nocopy<T2> simple_ptr_nocopy<T>::stat_cast(void) const {
375 simple_ptr_nocopy<T2> rtn;
376 T2* p = static_cast<T2*>(this->m_pointer);
377 if (p) rtn._make_alias(p, this->m_count);
381 template <typename T>
382 template <typename T2>
383 simple_ptr_nocopy<T2> simple_ptr_nocopy<T>::cast(void) const {
384 simple_ptr_nocopy<T2> rtn;
385 T2* p = (T2*)this->m_pointer;
386 if (p) rtn._make_alias(p, this->m_count);
392 ////////////////////////////////////////////////////////////////////////////////
394 } // end namespace stlplus