1*b3979f3aSjkunz /*
2*b3979f3aSjkunz  *  smart_ptr.h
3*b3979f3aSjkunz  *  elftosb
4*b3979f3aSjkunz  *
5*b3979f3aSjkunz  *  Created by Chris Reed on 4/18/06.
6*b3979f3aSjkunz  *  Copyright 2006 __MyCompanyName__. All rights reserved.
7*b3979f3aSjkunz  *
8*b3979f3aSjkunz  */
9*b3979f3aSjkunz #if !defined(_smart_ptr_h_)
10*b3979f3aSjkunz #define _smart_ptr_h_
11*b3979f3aSjkunz 
12*b3979f3aSjkunz /*!
13*b3979f3aSjkunz  * \brief Simple, standard smart pointer class.
14*b3979f3aSjkunz  *
15*b3979f3aSjkunz  * This class only supports the single-owner paradigm.
16*b3979f3aSjkunz  */
17*b3979f3aSjkunz template <typename T>
18*b3979f3aSjkunz class smart_ptr
19*b3979f3aSjkunz {
20*b3979f3aSjkunz public:
21*b3979f3aSjkunz 	typedef T data_type;
22*b3979f3aSjkunz 	typedef T * ptr_type;
23*b3979f3aSjkunz 	typedef const T * const_ptr_type;
24*b3979f3aSjkunz 	typedef T & ref_type;
25*b3979f3aSjkunz 	typedef const T & const_ref_type;
26*b3979f3aSjkunz 
27*b3979f3aSjkunz 	//! Default constuctor. Initialises with no pointer set.
smart_ptr()28*b3979f3aSjkunz 	smart_ptr() : _p(0) {}
29*b3979f3aSjkunz 
30*b3979f3aSjkunz 	//! This constructor takes a pointer to the object to be deleted.
smart_ptr(ptr_type p)31*b3979f3aSjkunz 	smart_ptr(ptr_type p) : _p(p) {}
32*b3979f3aSjkunz 
33*b3979f3aSjkunz 	//! Destructor. If an object (pointer) has been set, it will be deleted.
34*b3979f3aSjkunz 	//! Deletes the object using safe_delete().
~smart_ptr()35*b3979f3aSjkunz 	virtual ~smart_ptr() { safe_delete(); }
36*b3979f3aSjkunz 
37*b3979f3aSjkunz 	//! Return the current pointer value.
get()38*b3979f3aSjkunz 	ptr_type get() { return _p; }
39*b3979f3aSjkunz 
40*b3979f3aSjkunz 	//! Return the const form of the current pointer value.
get()41*b3979f3aSjkunz 	const_ptr_type get() const { return _p; }
42*b3979f3aSjkunz 
43*b3979f3aSjkunz 	//! Change the pointer value, or set if if the default constructor was used.
44*b3979f3aSjkunz 	//! If a pointer had previously been associated with the object, and \a p is
45*b3979f3aSjkunz 	//! different than that previous pointer, it will be deleted before taking
46*b3979f3aSjkunz 	//! ownership of \a p. If this is not desired, call reset() beforehand.
set(ptr_type p)47*b3979f3aSjkunz 	void set(ptr_type p)
48*b3979f3aSjkunz 	{
49*b3979f3aSjkunz 		if (_p && p != _p)
50*b3979f3aSjkunz 		{
51*b3979f3aSjkunz 			safe_delete();
52*b3979f3aSjkunz 		}
53*b3979f3aSjkunz 		_p = p;
54*b3979f3aSjkunz 	}
55*b3979f3aSjkunz 
56*b3979f3aSjkunz 	//! Dissociates any previously set pointer value without deleting it.
reset()57*b3979f3aSjkunz 	void reset() { _p = 0; }
58*b3979f3aSjkunz 
59*b3979f3aSjkunz 	//! Dissociates a previously set pointer value, deleting it at the same time.
clear()60*b3979f3aSjkunz 	void clear() { safe_delete(); }
61*b3979f3aSjkunz 
62*b3979f3aSjkunz 	//! Forces immediate deletion of the object. If you are planning on using
63*b3979f3aSjkunz 	//! this method, think about just using a normal pointer. It probably makes
64*b3979f3aSjkunz 	//! more sense.
safe_delete()65*b3979f3aSjkunz 	virtual void safe_delete()
66*b3979f3aSjkunz 	{
67*b3979f3aSjkunz 		if (_p)
68*b3979f3aSjkunz 		{
69*b3979f3aSjkunz 			delete _p;
70*b3979f3aSjkunz 			_p = 0;
71*b3979f3aSjkunz 		}
72*b3979f3aSjkunz 	}
73*b3979f3aSjkunz 
74*b3979f3aSjkunz 	//! \name Operators
75*b3979f3aSjkunz 	//@{
76*b3979f3aSjkunz 
77*b3979f3aSjkunz 	//! Makes the object transparent as the template type.
ptr_type()78*b3979f3aSjkunz 	operator ptr_type () { return _p; }
79*b3979f3aSjkunz 
80*b3979f3aSjkunz 	//! Const version of the pointer operator.
const_ptr_type()81*b3979f3aSjkunz 	operator const_ptr_type () const { return _p; }
82*b3979f3aSjkunz 
83*b3979f3aSjkunz 	//! Makes the object transparent as a reference of the template type.
ref_type()84*b3979f3aSjkunz 	operator ref_type () { return *_p; }
85*b3979f3aSjkunz 
86*b3979f3aSjkunz 	//! Const version of the reference operator.
const_ref_type()87*b3979f3aSjkunz 	operator const_ref_type () const { return *_p; }
88*b3979f3aSjkunz 
89*b3979f3aSjkunz 	//! Returns a boolean indicating whether the object has a pointer set or not.
90*b3979f3aSjkunz 	operator bool () const { return _p != 0; }
91*b3979f3aSjkunz 
92*b3979f3aSjkunz 	//! To allow setting the pointer directly. Equivalent to a call to set().
93*b3979f3aSjkunz 	smart_ptr<T> & operator = (const_ptr_type p)
94*b3979f3aSjkunz 	{
95*b3979f3aSjkunz 		set(const_cast<ptr_type>(p));
96*b3979f3aSjkunz 		return *this;
97*b3979f3aSjkunz 	}
98*b3979f3aSjkunz 
99*b3979f3aSjkunz 	//! Another operator to allow you to treat the object just like a pointer.
100*b3979f3aSjkunz 	ptr_type operator ->() { return _p; }
101*b3979f3aSjkunz 
102*b3979f3aSjkunz 	//! Another operator to allow you to treat the object just like a pointer.
103*b3979f3aSjkunz 	const_ptr_type operator ->() const { return _p; }
104*b3979f3aSjkunz 
105*b3979f3aSjkunz //	//! Pointer dereferencing operator.
106*b3979f3aSjkunz //	ref_type operator * () const { return *_p; }
107*b3979f3aSjkunz //
108*b3979f3aSjkunz //	//! Const version of the pointer dereference operator.
109*b3979f3aSjkunz //	const_ref_type operator * () const { return *_p; }
110*b3979f3aSjkunz 
111*b3979f3aSjkunz 	//@}
112*b3979f3aSjkunz 
113*b3979f3aSjkunz protected:
114*b3979f3aSjkunz 	ptr_type _p;	//!< The wrapped pointer.
115*b3979f3aSjkunz };
116*b3979f3aSjkunz 
117*b3979f3aSjkunz /*!
118*b3979f3aSjkunz  * \brief Simple, standard smart pointer class that uses the array delete operator.
119*b3979f3aSjkunz  *
120*b3979f3aSjkunz  * This class only supports the single-owner paradigm.
121*b3979f3aSjkunz  *
122*b3979f3aSjkunz  * This is almost entirely a copy of smart_ptr since the final C++ specification
123*b3979f3aSjkunz  * does not allow template subclass members to access members  of the parent that
124*b3979f3aSjkunz  * do not depend on the template parameter.
125*b3979f3aSjkunz  */
126*b3979f3aSjkunz template <typename T>
127*b3979f3aSjkunz class smart_array_ptr
128*b3979f3aSjkunz {
129*b3979f3aSjkunz public:
130*b3979f3aSjkunz 	typedef T data_type;
131*b3979f3aSjkunz 	typedef T * ptr_type;
132*b3979f3aSjkunz 	typedef const T * const_ptr_type;
133*b3979f3aSjkunz 	typedef T & ref_type;
134*b3979f3aSjkunz 	typedef const T & const_ref_type;
135*b3979f3aSjkunz 
136*b3979f3aSjkunz 	//! Default constuctor. Initialises with no pointer set.
smart_array_ptr()137*b3979f3aSjkunz 	smart_array_ptr() : _p(0) {}
138*b3979f3aSjkunz 
139*b3979f3aSjkunz 	//! This constructor takes a pointer to the object to be deleted.
smart_array_ptr(ptr_type p)140*b3979f3aSjkunz 	smart_array_ptr(ptr_type p) : _p(p) {}
141*b3979f3aSjkunz 
142*b3979f3aSjkunz 	//! Destructor. If an array has been set, it will be deleted.
143*b3979f3aSjkunz 	//! Deletes the array using safe_delete().
~smart_array_ptr()144*b3979f3aSjkunz 	virtual ~smart_array_ptr() { safe_delete(); }
145*b3979f3aSjkunz 
146*b3979f3aSjkunz 	//! Return the current pointer value.
get()147*b3979f3aSjkunz 	ptr_type get() { return _p; }
148*b3979f3aSjkunz 
149*b3979f3aSjkunz 	//! Return the const form of the current pointer value.
get()150*b3979f3aSjkunz 	const_ptr_type get() const { return _p; }
151*b3979f3aSjkunz 
152*b3979f3aSjkunz 	//! Change the pointer value, or set if if the default constructor was used.
153*b3979f3aSjkunz 	//! If a pointer had previously been associated with the object, and \a p is
154*b3979f3aSjkunz 	//! different than that previous pointer, it will be deleted before taking
155*b3979f3aSjkunz 	//! ownership of \a p. If this is not desired, call reset() beforehand.
set(ptr_type p)156*b3979f3aSjkunz 	void set(ptr_type p)
157*b3979f3aSjkunz 	{
158*b3979f3aSjkunz 		if (_p && p != _p)
159*b3979f3aSjkunz 		{
160*b3979f3aSjkunz 			safe_delete();
161*b3979f3aSjkunz 		}
162*b3979f3aSjkunz 		_p = p;
163*b3979f3aSjkunz 	}
164*b3979f3aSjkunz 
165*b3979f3aSjkunz 	//! Dissociates any previously set pointer value without deleting it.
reset()166*b3979f3aSjkunz 	void reset() { _p = 0; }
167*b3979f3aSjkunz 
168*b3979f3aSjkunz 	//! Dissociates a previously set pointer value, deleting it at the same time.
clear()169*b3979f3aSjkunz 	void clear() { safe_delete(); }
170*b3979f3aSjkunz 
171*b3979f3aSjkunz 	//! Forces immediate deletion of the object. If you are planning on using
172*b3979f3aSjkunz 	//! this method, think about just using a normal pointer. It probably makes
173*b3979f3aSjkunz 	//! more sense.
safe_delete()174*b3979f3aSjkunz 	virtual void safe_delete()
175*b3979f3aSjkunz 	{
176*b3979f3aSjkunz 		if (_p)
177*b3979f3aSjkunz 		{
178*b3979f3aSjkunz 			delete [] _p;
179*b3979f3aSjkunz 			_p = 0;
180*b3979f3aSjkunz 		}
181*b3979f3aSjkunz 	}
182*b3979f3aSjkunz 
183*b3979f3aSjkunz 	//! \name Operators
184*b3979f3aSjkunz 	//@{
185*b3979f3aSjkunz 
186*b3979f3aSjkunz 	//! Makes the object transparent as the template type.
ptr_type()187*b3979f3aSjkunz 	operator ptr_type () { return _p; }
188*b3979f3aSjkunz 
189*b3979f3aSjkunz 	//! Const version of the pointer operator.
const_ptr_type()190*b3979f3aSjkunz 	operator const_ptr_type () const { return _p; }
191*b3979f3aSjkunz 
192*b3979f3aSjkunz 	//! Makes the object transparent as a reference of the template type.
ref_type()193*b3979f3aSjkunz 	operator ref_type () { return *_p; }
194*b3979f3aSjkunz 
195*b3979f3aSjkunz 	//! Const version of the reference operator.
const_ref_type()196*b3979f3aSjkunz 	operator const_ref_type () const { return *_p; }
197*b3979f3aSjkunz 
198*b3979f3aSjkunz 	//! Returns a boolean indicating whether the object has a pointer set or not.
199*b3979f3aSjkunz 	operator bool () const { return _p != 0; }
200*b3979f3aSjkunz 
201*b3979f3aSjkunz 	//! To allow setting the pointer directly. Equivalent to a call to set().
202*b3979f3aSjkunz 	smart_array_ptr<T> & operator = (const_ptr_type p)
203*b3979f3aSjkunz 	{
204*b3979f3aSjkunz 		set(const_cast<ptr_type>(p));
205*b3979f3aSjkunz 		return *this;
206*b3979f3aSjkunz 	}
207*b3979f3aSjkunz 
208*b3979f3aSjkunz 	//! Another operator to allow you to treat the object just like a pointer.
209*b3979f3aSjkunz 	ptr_type operator ->() { return _p; }
210*b3979f3aSjkunz 
211*b3979f3aSjkunz 	//! Another operator to allow you to treat the object just like a pointer.
212*b3979f3aSjkunz 	const_ptr_type operator ->() const { return _p; }
213*b3979f3aSjkunz 
214*b3979f3aSjkunz 	//! Indexing operator.
215*b3979f3aSjkunz 	ref_type operator [] (unsigned index) { return _p[index]; }
216*b3979f3aSjkunz 
217*b3979f3aSjkunz 	//! Indexing operator.
218*b3979f3aSjkunz 	const_ref_type operator [] (unsigned index) const { return _p[index]; }
219*b3979f3aSjkunz 
220*b3979f3aSjkunz //	//! Pointer dereferencing operator.
221*b3979f3aSjkunz //	ref_type operator * () const { return *_p; }
222*b3979f3aSjkunz //
223*b3979f3aSjkunz //	//! Const version of the pointer dereference operator.
224*b3979f3aSjkunz //	const_ref_type operator * () const { return *_p; }
225*b3979f3aSjkunz 
226*b3979f3aSjkunz 	//@}
227*b3979f3aSjkunz 
228*b3979f3aSjkunz protected:
229*b3979f3aSjkunz 	ptr_type _p;	//!< The wrapped pointer.
230*b3979f3aSjkunz };
231*b3979f3aSjkunz 
232*b3979f3aSjkunz #endif // _smart_ptr_h_
233