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