]> Dogcows Code - chaz/yoink/blob - src/stlplus/containers/simple_ptr.tpp
ead6744035fe76fe087ceb32928789fe94802840
[chaz/yoink] / src / stlplus / containers / simple_ptr.tpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Daniel Milton
4 // Copyright: (c) Daniel Milton 2002-2009
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 #ifdef STLPLUS_MEMBER_TEMPLATES
254
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
259 {
260 simple_ptr_base<T2,C> rtn;
261 rtn.m_pointer = dynamic_cast<T2*>(m_pointer);
262 if (rtn.m_pointer) {
263 delete rtn.m_count;
264 rtn.m_count = m_count;
265 rtn.increment();
266 }
267 return rtn;
268 }
269
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
274 {
275 simple_ptr_base<T2,C> rtn;
276 rtn.m_pointer = static_cast<T2*>(m_pointer);
277 if (rtn.m_pointer) {
278 delete rtn.m_count;
279 rtn.m_count = m_count;
280 rtn.increment();
281 }
282 return rtn;
283 }
284
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
289 {
290 simple_ptr_base<T2,C> rtn;
291 rtn.m_pointer = (T2*)m_pointer;
292 if (rtn.m_pointer) {
293 delete rtn.m_count;
294 rtn.m_count = m_count;
295 rtn.increment();
296 }
297 return rtn;
298 }
299
300 #endif
301
302 // internal function for distinguishing unique simple_ptr objects
303 // used for example in persistence routines
304
305 template <typename T, typename C>
306 unsigned* simple_ptr_base<T,C>::_count(void) const
307 {
308 return m_count;
309 }
310
311 template <typename T, typename C>
312 T* simple_ptr_base<T,C>::_pointer(void) const
313 {
314 return m_pointer;
315 }
316
317 template <typename T, typename C>
318 void simple_ptr_base<T,C>::_make_alias(T* pointer, unsigned* count)
319 {
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)
323 {
324 if(decrement())
325 {
326 delete m_pointer;
327 delete m_count;
328 }
329 m_pointer = pointer;
330 m_count = count;
331 increment();
332 }
333 }
334
335 ////////////////////////////////////////////////////////////////////////////////
336
337 } // end namespace stlplus
338
This page took 0.058139 seconds and 3 git commands to generate.