]> Dogcows Code - chaz/yoink/blob - src/stlplus/containers/simple_ptr.hpp
72d1db7e16d0bf15efed1cd6c9dba1103fd1efb3
[chaz/yoink] / src / stlplus / containers / simple_ptr.hpp
1 #ifndef STLPLUS_SIMPLE_PTR
2 #define STLPLUS_SIMPLE_PTR
3 ////////////////////////////////////////////////////////////////////////////////
4
5 // Author: Daniel Milton, Andy Rushton
6 // Copyright: (c) Southampton University 1999-2004
7 // (c) Daniel Milton, Andy Rushton 2004-2009
8 // License: BSD License, see ../docs/license.html
9
10 // A smart pointer is a memory-managing pointer to an object. If you like, it
11 // is a zero-dimensional container.
12
13 // Assignment of smart pointers result in multiple aliases of the same object.
14 // The term alias is used to differentiate from conventional pointers because
15 // the semantics are different.
16
17 // Aliases can be turned into copies if the pointed-to class supports copying.
18
19 // These simple_ptr classes from DJDM have slightly different semantics than
20 // the smart_ptr classes of AJR. There are no cross-pointer side effects
21 // that occur when the pointer is cleared. The clear() function is effectively
22 // equivalent to the clear_unique() function of the smart_ptr. The only way
23 // that a "referenced" object will be deleted is if all simple_ptr's that
24 // reference the object are cleared (by deletion, manual clearing or reassignment).
25
26 // Also, the simple pointer cannot contain a reference to a shared null pointer
27 // (which occurs as a side-effect of clearing a multiply referenced object in
28 // the smart_ptr classes). Which means that if you have a null simple_ptr, then
29 // the assignment of any other null simple_ptr will NOT reassign the reference of
30 // any other simple_ptr. Hence, the simple_ptr class acts a little more like a
31 // normal pointer (with fewer side effects), with the added bonus of containment.
32
33 // Due to the way that the simple_ptr contains the data, it also allows the
34 // addition of various casting functions, while still keeping the managed data
35 // containment functionality of the underlying object. This means that you can
36 // have two simple_ptr's of different template types, both pointing to the same
37 // data (if the differing template types are derivatives of each other).
38
39 // The base class is simple_ptr_base which defines the common interface. Then
40 // there are three subclasses which have the same interface but different copy
41 // semantics:
42
43 // - simple_ptr for simple types and classes which have copy constructors
44 // - simple_ptr_clone for polymorphic class hierarchies which are copied using a clone method
45 // - simple_ptr_nocopy for any class that cannot or should not be copied
46
47 ////////////////////////////////////////////////////////////////////////////////
48 #include "containers_fixes.hpp"
49 #include "exceptions.hpp"
50 #include "copy_functors.hpp"
51 #include <map>
52 #include <string>
53
54 namespace stlplus
55 {
56
57 ////////////////////////////////////////////////////////////////////////////////
58 // Base class
59 ////////////////////////////////////////////////////////////////////////////////
60
61 template<typename T, typename C>
62 class simple_ptr_base
63 {
64 public:
65 //////////////////////////////////////////////////////////////////////////////
66 // member type definitions
67
68 typedef T value_type;
69 typedef T& reference;
70 typedef const T& const_reference;
71 typedef C value_copy;
72
73 //////////////////////////////////////////////////////////////////////////////
74 // constructors and destructors
75
76 // create a null pointer
77 simple_ptr_base(void);
78
79 // create a pointer containing a *copy* of the object using the template parameter C
80 // this copy is taken because the pointer class maintains a dynamically allocated object
81 // and the T& may not be (usually is not) dynamically allocated
82 explicit simple_ptr_base(const T& data) throw(illegal_copy);
83
84 // create a pointer containing a dynamically created object
85 // Note: the object must be allocated *by the user* with new
86 // constructor form - must be called in the form smart_ptr_base<type> x(new type(args))
87 explicit simple_ptr_base(T* data);
88
89 // copy constructor implements aliasing so no copy is made
90 // note that the copy constructor should NOT be explicit, as this breaks
91 // the returning of pointer objects from functions (at least within GCC 4.4)
92 simple_ptr_base(const simple_ptr_base<T,C>& r);
93
94 // assignment operator - required, else the output of GCC suffers segmentation faults
95 simple_ptr_base<T,C>& operator=(const simple_ptr_base<T,C>& r);
96
97 // destructor decrements the reference count and delete only when the last reference is destroyed
98 ~simple_ptr_base(void);
99
100 //////////////////////////////////////////////////////////////////////////////
101 // logical tests to see if there is anything contained in the pointer since it can be null
102
103 // there are two forms:explicit and implicit
104 // implicit: if(!r) or if(r)
105 // explicit: if(r.null()) or if(r.present())
106 operator bool(void) const;
107 bool operator!(void) const;
108 bool present(void) const;
109 bool null(void) const;
110
111 //////////////////////////////////////////////////////////////////////////////
112 // dereference operators and functions
113
114 // dereference the smart pointer to get the object - use in the form *p1
115 T& operator*(void) throw(null_dereference);
116 const T& operator*(void) const throw(null_dereference);
117
118 // used as a prefix to a member access to the contained object e.g. p1->print() calls T::print()
119 T* operator->(void) throw(null_dereference);
120 const T* operator->(void) const throw(null_dereference);
121
122 //////////////////////////////////////////////////////////////////////////////
123 // explicit function forms of the above assignment and dereference operators
124
125 // set the value - note that this does a copy using the C template parameter
126 void set_value(const T& data) throw(illegal_copy);
127 // get the value
128 T& value(void) throw(null_dereference);
129 const T& value(void) const throw(null_dereference);
130
131 // set the pointer
132 // deletes the previous pointer and adopts the passed pointer instead
133 // Note: the object must be allocated *by the user* with new
134 // Warning: it is very easy to break the memory management with this operation
135 void set(T* data = 0);
136 // get the pointer
137 T* pointer(void);
138 const T* pointer(void) const;
139
140 //////////////////////////////////////////////////////////////////////////////
141 // functions to manage aliases
142
143 // make this an alias of the passed object
144 void alias(const simple_ptr_base<T,C>&);
145
146 // test whether two pointers point to the same object(known as aliasing the object)
147 // used in the form if(a.aliases(b))
148 bool aliases(const simple_ptr_base<T,C>&) const;
149
150 // find the number of aliases - used when you need to know whether an
151 // object is still referred to from elsewhere (rare!)
152 unsigned alias_count(void) const;
153
154 // clear the reference to the object, but only delete the object if there are no
155 // other references to that object. Hence, this does not affect other pointers
156 // that are pointing to the same object.
157 void clear(void);
158
159 // This is just an alias of the clear() function, provided for completeness of
160 // the interface when acting as a replacement for the smart_ptr classes
161 void clear_unique(void);
162
163 //////////////////////////////////////////////////////////////////////////////
164 // functions that involve copying
165
166 // these functions use the copy functor passed as the template parameter C
167 // to copy the object with the right copy semantics. If the copy functor
168 // is no_copy, an exception will be thrown.
169
170 // make this pointer unique with respect to any other references to the same object
171 // if this pointer is already unique, it does nothing - otherwise it copies the object
172 void make_unique(void) throw(illegal_copy);
173
174 // make this pointer a unique copy of the parameter
175 // useful for expressions like p1.copy(p2) which makes p1 a pointer to a unique copy of the contents of p2
176 void copy(const simple_ptr_base<T,C>&) throw(illegal_copy);
177
178 //////////////////////////////////////////////////////////////////////////////
179 // functions that involve casting
180
181 #ifdef STLPLUS_MEMBER_TEMPLATES
182
183 // dynamic cast of underlying pointer to a derived/parent
184 template<typename T2> simple_ptr_base<T2,C> dyn_cast(void) const;
185
186 // static cast of underlying pointer to a derived/parent
187 template<typename T2> simple_ptr_base<T2,C> stat_cast(void) const;
188
189 // cast of underlying pointer to a base - while keeping the same ref-counted object
190 template<typename T2> simple_ptr_base<T2,C> cast(void) const;
191
192 #endif
193
194 //////////////////////////////////////////////////////////////////////////////
195
196 protected:
197 T* m_pointer;
198 unsigned* m_count;
199
200 public:
201 // internal use only - had to make them public because they need to be
202 // accessed by routines that could not be made friends
203 // can't have a handle due to the way the simple pointer stores it's data
204 // in separate counter and pointer objects
205 unsigned* _count(void) const;
206 T* _pointer(void) const;
207 void _make_alias(T* pointer, unsigned* count);
208
209 private:
210 void increment(void);
211 bool decrement(void);
212 };
213
214 ////////////////////////////////////////////////////////////////////////////////
215 // simple_ptr for simple types and classes which have copy constructors
216
217 template <typename T>
218 class simple_ptr : public simple_ptr_base<T, constructor_copy<T> >
219 {
220 public:
221 simple_ptr(void) {}
222 explicit simple_ptr(const T& data) : simple_ptr_base<T, constructor_copy<T> >(data) {}
223 explicit simple_ptr(T* data) : simple_ptr_base<T, constructor_copy<T> >(data) {}
224 simple_ptr<T>& operator=(const T& data) {set_value(data); return *this;}
225 simple_ptr<T>& operator=(T* data) {set(data); return *this;}
226 ~simple_ptr(void) {}
227 };
228
229 ////////////////////////////////////////////////////////////////////////////////
230 // smart_ptr_clone for polymorphic class hierarchies which have a clone method
231
232 template <typename T>
233 class simple_ptr_clone : public simple_ptr_base<T, clone_copy<T> >
234 {
235 public:
236 simple_ptr_clone(void) {}
237 explicit simple_ptr_clone(const T& data) : simple_ptr_base<T, clone_copy<T> >(data) {}
238 explicit simple_ptr_clone(T* data) : simple_ptr_base<T, clone_copy<T> >(data) {}
239 simple_ptr_clone<T>& operator=(const T& data) {set_value(data); return *this;}
240 simple_ptr_clone<T>& operator=(T* data) {set(data); return *this;}
241 ~simple_ptr_clone(void) {}
242 };
243
244 ////////////////////////////////////////////////////////////////////////////////
245 // smart_ptr_nocopy for any class that cannot or should not be copied
246
247 template <typename T>
248 class simple_ptr_nocopy : public simple_ptr_base<T, no_copy<T> >
249 {
250 public:
251 simple_ptr_nocopy(void) {}
252 explicit simple_ptr_nocopy(const T& data) : simple_ptr_base<T, no_copy<T> >(data) {}
253 explicit simple_ptr_nocopy(T* data) : simple_ptr_base<T, no_copy<T> >(data) {}
254 simple_ptr_nocopy<T>& operator=(const T& data) {set_value(data); return *this;}
255 simple_ptr_nocopy<T>& operator=(T* data) {set(data); return *this;}
256 ~simple_ptr_nocopy(void) {}
257 };
258
259 ////////////////////////////////////////////////////////////////////////////////
260
261 } // end namespace stlplus
262
263 #include "simple_ptr.tpp"
264 #endif
This page took 0.040469 seconds and 3 git commands to generate.