]>
Dogcows Code - chaz/yoink/blob - src/stlplus/containers/simple_ptr.hpp
ffe2c8afeee60a56feeab042205db5a54f5b013f
1 #ifndef STLPLUS_SIMPLE_PTR
2 #define STLPLUS_SIMPLE_PTR
3 ////////////////////////////////////////////////////////////////////////////////
5 // Author: Daniel Milton
6 // Copyright: (c) Daniel Milton 2002 onwards
7 // License: BSD License, see ../docs/license.html
9 // A smart pointer is a memory-managing pointer to an object. If you like, it
10 // is a zero-dimensional container.
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.
16 // Aliases can be turned into copies if the pointed-to class supports copying.
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).
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.
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).
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
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
46 ////////////////////////////////////////////////////////////////////////////////
47 #include "containers_fixes.hpp"
48 #include "exceptions.hpp"
49 #include "copy_functors.hpp"
56 ////////////////////////////////////////////////////////////////////////////////
58 ////////////////////////////////////////////////////////////////////////////////
60 template<typename T
, typename C
>
64 //////////////////////////////////////////////////////////////////////////////
65 // member type definitions
69 typedef const T
& const_reference
;
72 //////////////////////////////////////////////////////////////////////////////
73 // constructors and destructors
75 // create a null pointer
76 simple_ptr_base(void);
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
);
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
);
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
);
91 // destructor decrements the reference count and delete only when the last reference is destroyed
92 ~simple_ptr_base(void);
94 //////////////////////////////////////////////////////////////////////////////
95 // logical tests to see if there is anything contained in the pointer since it can be null
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;
105 //////////////////////////////////////////////////////////////////////////////
106 // dereference operators and functions
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
);
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
);
116 //////////////////////////////////////////////////////////////////////////////
117 // explicit function forms of the above assignment and dereference operators
120 T
& value(void) throw(null_dereference
);
121 const T
& value(void) const throw(null_dereference
);
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);
130 const T
* pointer(void) const;
132 //////////////////////////////////////////////////////////////////////////////
133 // functions to manage aliases
135 // make this an alias of the passed object
136 void alias(const simple_ptr_base
<T
,C
>&);
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;
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;
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.
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);
155 //////////////////////////////////////////////////////////////////////////////
156 // functions that involve copying
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.
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
);
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
);
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
);
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
);
178 //////////////////////////////////////////////////////////////////////////////
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
);
194 void increment(void);
195 bool decrement(void);
198 ////////////////////////////////////////////////////////////////////////////////
199 // simple_ptr for simple types and classes which have copy constructors
201 template <typename T
>
202 class simple_ptr
: public simple_ptr_base
<T
, constructor_copy
<T
> >
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;}
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:
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.
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.
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.
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;
233 ////////////////////////////////////////////////////////////////////////////////
234 // simple_ptr_clone for polymorphic class hierarchies which have a clone method
236 template <typename T
>
237 class simple_ptr_clone
: public simple_ptr_base
<T
, clone_copy
<T
> >
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) {}
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;
256 ////////////////////////////////////////////////////////////////////////////////
257 // simple_ptr_nocopy for any class that cannot or should not be copied
259 template <typename T
>
260 class simple_ptr_nocopy
: public simple_ptr_base
<T
, no_copy
<T
> >
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) {}
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;
277 ////////////////////////////////////////////////////////////////////////////////
279 } // end namespace stlplus
281 #include "simple_ptr.tpp"
This page took 0.047529 seconds and 4 git commands to generate.