]> Dogcows Code - chaz/yoink/blob - src/stlplus/containers/smart_ptr.tpp
fixes for newer versions of g++
[chaz/yoink] / src / stlplus / containers / smart_ptr.tpp
1 ////////////////////////////////////////////////////////////////////////////////
2
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
7
8 ////////////////////////////////////////////////////////////////////////////////
9
10 namespace stlplus
11 {
12
13 ////////////////////////////////////////////////////////////////////////////////
14 // internal holder data structure
15 ////////////////////////////////////////////////////////////////////////////////
16
17 template<typename T>
18 class smart_ptr_holder
19 {
20 private:
21 unsigned m_count;
22 T* m_data;
23
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) :
26 m_count(0), m_data(0)
27 {
28 }
29
30 smart_ptr_holder& operator=(const smart_ptr_holder& s)
31 {
32 return *this;
33 }
34
35 public:
36 smart_ptr_holder(T* p = 0) :
37 m_count(1), m_data(p)
38 {
39 }
40
41 ~smart_ptr_holder(void)
42 {
43 clear();
44 }
45
46 unsigned count(void) const
47 {
48 return m_count;
49 }
50
51 void increment(void)
52 {
53 ++m_count;
54 }
55
56 bool decrement(void)
57 {
58 --m_count;
59 return m_count == 0;
60 }
61
62 bool null(void)
63 {
64 return m_data == 0;
65 }
66
67 void clear(void)
68 {
69 if(m_data)
70 delete m_data;
71 m_data = 0;
72 }
73
74 void set(T* p = 0)
75 {
76 clear();
77 m_data = p;
78 }
79
80 T*& pointer(void)
81 {
82 return m_data;
83 }
84
85 const T* pointer(void) const
86 {
87 return m_data;
88 }
89
90 T& value(void)
91 {
92 return *m_data;
93 }
94
95 const T& value(void) const
96 {
97 return *m_data;
98 }
99 };
100
101 ////////////////////////////////////////////////////////////////////////////////
102 // smart_ptr_base class
103 ////////////////////////////////////////////////////////////////////////////////
104
105 ////////////////////////////////////////////////////////////////////////////////
106 // constructors, assignments and destructors
107
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>)
112 {
113 }
114
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>)
119 {
120 m_holder->set(C()(data));
121 }
122
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>)
129 {
130 m_holder->set(data);
131 }
132
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) :
136 m_holder(0)
137 {
138 m_holder = r.m_holder;
139 m_holder->increment();
140 }
141
142 // assignment operator - required, else the output of GCC suffers segmentation faults
143 template <typename T, typename C>
144 smart_ptr_base<T,C>& smart_ptr_base<T,C>::operator=(const smart_ptr_base<T,C>& r)
145 {
146 alias(r);
147 return *this;
148 }
149
150 // destructor decrements the reference count and delete only when the last reference is destroyed
151 template <typename T, typename C>
152 smart_ptr_base<T,C>::~smart_ptr_base(void)
153 {
154 if(m_holder->decrement())
155 delete m_holder;
156 }
157
158 //////////////////////////////////////////////////////////////////////////////
159 // logical tests to see if there is anything contained in the pointer since it can be null
160
161 template <typename T, typename C>
162 bool smart_ptr_base<T,C>::null(void) const
163 {
164 return m_holder->null();
165 }
166
167 template <typename T, typename C>
168 bool smart_ptr_base<T,C>::present(void) const
169 {
170 return !m_holder->null();
171 }
172
173 template <typename T, typename C>
174 bool smart_ptr_base<T,C>::operator!(void) const
175 {
176 return m_holder->null();
177 }
178
179 template <typename T, typename C>
180 smart_ptr_base<T,C>::operator bool(void) const
181 {
182 return !m_holder->null();
183 }
184
185 //////////////////////////////////////////////////////////////////////////////
186 // dereference operators and functions
187
188 template <typename T, typename C>
189 T& smart_ptr_base<T,C>::operator*(void) throw(null_dereference)
190 {
191 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
192 return m_holder->value();
193 }
194
195 template <typename T, typename C>
196 const T& smart_ptr_base<T,C>::operator*(void) const throw(null_dereference)
197 {
198 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
199 return m_holder->value();
200 }
201
202 template <typename T, typename C>
203 T* smart_ptr_base<T,C>::operator->(void) throw(null_dereference)
204 {
205 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
206 return m_holder->pointer();
207 }
208
209 template <typename T, typename C>
210 const T* smart_ptr_base<T,C>::operator->(void) const throw(null_dereference)
211 {
212 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
213 return m_holder->pointer();
214 }
215
216 //////////////////////////////////////////////////////////////////////////////
217 // explicit function forms of the above assignment dereference operators
218
219 template <typename T, typename C>
220 void smart_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)
221 {
222 m_holder->set(C()(data));
223 }
224
225 template <typename T, typename C>
226 T& smart_ptr_base<T,C>::value(void) throw(null_dereference)
227 {
228 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
229 return m_holder->value();
230 }
231
232 template <typename T, typename C>
233 const T& smart_ptr_base<T,C>::value(void) const throw(null_dereference)
234 {
235 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
236 return m_holder->value();
237 }
238
239 template <typename T, typename C>
240 void smart_ptr_base<T,C>::set(T* data)
241 {
242 m_holder->set(data);
243 }
244
245 template <typename T, typename C>
246 T* smart_ptr_base<T,C>::pointer(void)
247 {
248 return m_holder->pointer();
249 }
250
251 template <typename T, typename C>
252 const T* smart_ptr_base<T,C>::pointer(void) const
253 {
254 return m_holder->pointer();
255 }
256
257 ////////////////////////////////////////////////////////////////////////////////
258 // functions to manage counted referencing
259
260 // make this an alias of the passed object
261 template <typename T, typename C>
262 void smart_ptr_base<T,C>::alias(const smart_ptr_base<T,C>& r)
263 {
264 _make_alias(r.m_holder);
265 }
266
267 template <typename T, typename C>
268 bool smart_ptr_base<T,C>::aliases(const smart_ptr_base<T,C>& r) const
269 {
270 return m_holder == r.m_holder;
271 }
272
273 template <typename T, typename C>
274 unsigned smart_ptr_base<T,C>::alias_count(void) const
275 {
276 return m_holder->count();
277 }
278
279 template <typename T, typename C>
280 void smart_ptr_base<T,C>::clear(void)
281 {
282 m_holder->clear();
283 }
284
285 template <typename T, typename C>
286 void smart_ptr_base<T,C>::clear_unique(void)
287 {
288 if (m_holder->count() == 1)
289 m_holder->clear();
290 else
291 {
292 m_holder->decrement();
293 m_holder = 0;
294 m_holder = new smart_ptr_holder<T>;
295 }
296 }
297
298 template <typename T, typename C>
299 void smart_ptr_base<T,C>::make_unique(void) throw(illegal_copy)
300 {
301 if (m_holder->count() > 1)
302 {
303 smart_ptr_holder<T>* old_holder = m_holder;
304 m_holder->decrement();
305 m_holder = 0;
306 m_holder = new smart_ptr_holder<T>;
307 if (old_holder->pointer())
308 m_holder->set(C()(old_holder->value()));
309 }
310 }
311
312 template <typename T, typename C>
313 void smart_ptr_base<T,C>::copy(const smart_ptr_base<T,C>& data) throw(illegal_copy)
314 {
315 alias(data);
316 make_unique();
317 }
318
319 // internal function for distinguishing unique smart_ptr objects
320 // used for example in persistence routines
321
322 template <typename T, typename C>
323 smart_ptr_holder<T>* smart_ptr_base<T,C>::_handle(void) const
324 {
325 return m_holder;
326 }
327
328 template <typename T, typename C>
329 void smart_ptr_base<T,C>::_make_alias(smart_ptr_holder<T>* r_holder)
330 {
331 // make it alias-copy safe - this means that I don't try to do the
332 // assignment if r is either the same object or an alias of it
333 if (m_holder != r_holder)
334 {
335 if (m_holder->decrement())
336 delete m_holder;
337 m_holder = r_holder;
338 m_holder->increment();
339 }
340 }
341
342 ////////////////////////////////////////////////////////////////////////////////
343
344 } // end namespace stlplus
345
This page took 0.044949 seconds and 4 git commands to generate.