]> Dogcows Code - chaz/yoink/blob - src/stlplus/containers/simple_ptr.tpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / containers / simple_ptr.tpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Daniel Milton
4 // Copyright: (c) Daniel Milton 2002 onwards
5
6 ////////////////////////////////////////////////////////////////////////////////
7
8 namespace stlplus
9 {
10
11 ////////////////////////////////////////////////////////////////////////////////
12 // simple_ptr_base class
13 ////////////////////////////////////////////////////////////////////////////////
14
15 ////////////////////////////////////////////////////////////////////////////////
16 // constructors, assignments and destructors
17
18 // create a null pointer
19 template <typename T, typename C>
20 simple_ptr_base<T,C>::simple_ptr_base(void) :
21 m_pointer(0),
22 m_count(new unsigned(1))
23 {
24 }
25
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) :
29 m_pointer(C()(data)),
30 m_count(new unsigned(1))
31 {
32 }
33
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) :
39 m_pointer(data),
40 m_count(new unsigned(1))
41 {
42 }
43
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),
48 m_count(r.m_count)
49 {
50 increment();
51 }
52
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)
56 {
57 alias(r);
58 return *this;
59 }
60
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)
64 {
65 if(decrement())
66 {
67 delete m_pointer;
68 delete m_count;
69 }
70 }
71
72 //////////////////////////////////////////////////////////////////////////////
73 // logical tests to see if there is anything contained in the pointer since it can be null
74
75 template <typename T, typename C>
76 bool simple_ptr_base<T,C>::null(void) const
77 {
78 return m_pointer==0;
79 }
80
81 template <typename T, typename C>
82 bool simple_ptr_base<T,C>::present(void) const
83 {
84 return m_pointer!=0;
85 }
86
87 template <typename T, typename C>
88 bool simple_ptr_base<T,C>::operator!(void) const
89 {
90 return m_pointer==0;
91 }
92
93 template <typename T, typename C>
94 simple_ptr_base<T,C>::operator bool(void) const
95 {
96 return m_pointer!=0;
97 }
98
99 //////////////////////////////////////////////////////////////////////////////
100 // dereference operators and functions
101
102 template <typename T, typename C>
103 T& simple_ptr_base<T,C>::operator*(void) throw(null_dereference)
104 {
105 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator*");
106 return *m_pointer;
107 }
108
109 template <typename T, typename C>
110 const T& simple_ptr_base<T,C>::operator*(void) const throw(null_dereference)
111 {
112 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator*");
113 return *m_pointer;
114 }
115
116 template <typename T, typename C>
117 T* simple_ptr_base<T,C>::operator->(void) throw(null_dereference)
118 {
119 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator->");
120 return m_pointer;
121 }
122
123 template <typename T, typename C>
124 const T* simple_ptr_base<T,C>::operator->(void) const throw(null_dereference)
125 {
126 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::operator->");
127 return m_pointer;
128 }
129
130 //////////////////////////////////////////////////////////////////////////////
131 // explicit function forms of the above assignment dereference operators
132
133 template <typename T, typename C>
134 void simple_ptr_base<T,C>::set_value(const T& data) throw(illegal_copy)
135 {
136 set(C()(data));
137 }
138
139 template <typename T, typename C>
140 T& simple_ptr_base<T,C>::value(void) throw(null_dereference)
141 {
142 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::value");
143 return *m_pointer;
144 }
145
146 template <typename T, typename C>
147 const T& simple_ptr_base<T,C>::value(void) const throw(null_dereference)
148 {
149 if (!m_pointer) throw null_dereference("null pointer dereferenced in simple_ptr::value");
150 return *m_pointer;
151 }
152
153 template <typename T, typename C>
154 void simple_ptr_base<T,C>::set(T* data)
155 {
156 unsigned& count = *m_count;
157 if (count<=1)
158 delete m_pointer;
159 else
160 {
161 --count;
162 m_count = new unsigned(1);
163 }
164 m_pointer = data;
165 }
166
167 template <typename T, typename C>
168 T* simple_ptr_base<T,C>::pointer(void)
169 {
170 return m_pointer;
171 }
172
173 template <typename T, typename C>
174 const T* simple_ptr_base<T,C>::pointer(void) const
175 {
176 return m_pointer;
177 }
178
179 ////////////////////////////////////////////////////////////////////////////////
180 // functions to manage counted referencing
181
182 template <typename T, typename C>
183 void simple_ptr_base<T,C>::increment(void)
184 {
185 ++(*m_count);
186 }
187
188 template <typename T, typename C>
189 bool simple_ptr_base<T,C>::decrement(void)
190 {
191 unsigned& count = *m_count;
192 --count;
193 return count == 0;
194 }
195
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)
199 {
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;
203 if(decrement()) {
204 delete m_pointer;
205 delete m_count;
206 }
207 m_pointer = r.m_pointer;
208 m_count = r.m_count;
209 increment();
210 }
211
212 template <typename T, typename C>
213 bool simple_ptr_base<T,C>::aliases(const simple_ptr_base<T,C>& r) const
214 {
215 return m_count == r.m_count;
216 }
217
218 template <typename T, typename C>
219 unsigned simple_ptr_base<T,C>::alias_count(void) const
220 {
221 return *m_count;
222 }
223
224 template <typename T, typename C>
225 void simple_ptr_base<T,C>::clear(void)
226 {
227 set(0);
228 }
229
230 template <typename T, typename C>
231 void simple_ptr_base<T,C>::clear_unique(void)
232 {
233 set(0); // no difference between clear and clear_unique with the simple_ptr
234 }
235
236 template <typename T, typename C>
237 void simple_ptr_base<T,C>::make_unique(void) throw(illegal_copy)
238 {
239 unsigned& count = *m_count;
240 if (count <= 1) return;
241 --count;
242 if (m_pointer) m_pointer = C()(*m_pointer);
243 m_count = new unsigned(1);
244 }
245
246 template <typename T, typename C>
247 void simple_ptr_base<T,C>::copy(const simple_ptr_base<T,C>& data) throw(illegal_copy)
248 {
249 alias(data);
250 make_unique();
251 }
252
253 // internal function for distinguishing unique simple_ptr objects
254 // used for example in persistence routines
255
256 template <typename T, typename C>
257 unsigned* simple_ptr_base<T,C>::_count(void) const
258 {
259 return m_count;
260 }
261
262 template <typename T, typename C>
263 T* simple_ptr_base<T,C>::_pointer(void) const
264 {
265 return m_pointer;
266 }
267
268 template <typename T, typename C>
269 void simple_ptr_base<T,C>::_make_alias(T* pointer, unsigned* count)
270 {
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)
274 {
275 if(decrement())
276 {
277 delete m_pointer;
278 delete m_count;
279 }
280 m_pointer = pointer;
281 m_count = count;
282 increment();
283 }
284 }
285
286
287 ////////////////////////////////////////////////////////////////////////////////
288 // simple_ptr class
289 ////////////////////////////////////////////////////////////////////////////////
290
291 #ifdef STLPLUS_MEMBER_TEMPLATES
292
293 template <typename T>
294 template <typename T2>
295 simple_ptr<T2> simple_ptr<T>::dyn_cast(void) const {
296 simple_ptr<T2> rtn;
297 T2* p = dynamic_cast<T2*>(this->m_pointer);
298 if (p) rtn._make_alias(p, this->m_count);
299 return rtn;
300 }
301
302 template <typename T>
303 template <typename T2>
304 simple_ptr<T2> simple_ptr<T>::stat_cast(void) const {
305 simple_ptr<T2> rtn;
306 T2* p = static_cast<T2*>(this->m_pointer);
307 if (p) rtn._make_alias(p, this->m_count);
308 return rtn;
309 }
310
311 template <typename T>
312 template <typename T2>
313 simple_ptr<T2> simple_ptr<T>::cast(void) const {
314 simple_ptr<T2> rtn;
315 T2* p = (T2*)this->m_pointer;
316 if (p) rtn._make_alias(p, this->m_count);
317 return rtn;
318 }
319
320 #endif
321
322 ////////////////////////////////////////////////////////////////////////////////
323 // simple_ptr_clone class
324 ////////////////////////////////////////////////////////////////////////////////
325
326 #ifdef STLPLUS_MEMBER_TEMPLATES
327
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);
334 return rtn;
335 }
336
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);
343 return rtn;
344 }
345
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);
352 return rtn;
353 }
354
355 #endif
356
357 ////////////////////////////////////////////////////////////////////////////////
358 // simple_ptr_nocopy class
359 ////////////////////////////////////////////////////////////////////////////////
360
361 #ifdef STLPLUS_MEMBER_TEMPLATES
362
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);
369 return rtn;
370 }
371
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);
378 return rtn;
379 }
380
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);
387 return rtn;
388 }
389
390 #endif
391
392 ////////////////////////////////////////////////////////////////////////////////
393
394 } // end namespace stlplus
395
This page took 0.046613 seconds and 4 git commands to generate.