1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Daniel Milton
4 // Copyright: (c) Daniel Milton 2002-2009
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 #ifdef STLPLUS_MEMBER_TEMPLATES
255 // dynamic cast of underlying pointer to a derived/parent
256 template <typename T, typename C>
257 template <typename T2>
258 simple_ptr_base<T2,C> simple_ptr_base<T,C>::dyn_cast(void) const
260 simple_ptr_base<T2,C> rtn;
261 rtn.m_pointer = dynamic_cast<T2*>(m_pointer);
264 rtn.m_count = m_count;
270 // static cast of underlying pointer to a derived/parent
271 template <typename T, typename C>
272 template <typename T2>
273 simple_ptr_base<T2,C> simple_ptr_base<T,C>::stat_cast(void) const
275 simple_ptr_base<T2,C> rtn;
276 rtn.m_pointer = static_cast<T2*>(m_pointer);
279 rtn.m_count = m_count;
285 // cast of underlying pointer to a base - while keeping the same ref-counted object
286 template <typename T, typename C>
287 template <typename T2>
288 simple_ptr_base<T2,C> simple_ptr_base<T,C>::cast(void) const
290 simple_ptr_base<T2,C> rtn;
291 rtn.m_pointer = (T2*)m_pointer;
294 rtn.m_count = m_count;
302 // internal function for distinguishing unique simple_ptr objects
303 // used for example in persistence routines
305 template <typename T, typename C>
306 unsigned* simple_ptr_base<T,C>::_count(void) const
311 template <typename T, typename C>
312 T* simple_ptr_base<T,C>::_pointer(void) const
317 template <typename T, typename C>
318 void simple_ptr_base<T,C>::_make_alias(T* pointer, unsigned* count)
320 // make it alias-copy safe - this means that I don't try to do the
321 // assignment if r is either the same object or an alias of it
322 if (m_count != count)
335 ////////////////////////////////////////////////////////////////////////////////
337 } // end namespace stlplus