2 #ifndef _GLIBMM_REFPTR_H
3 #define _GLIBMM_REFPTR_H
5 /* $Id: refptr.h 216 2005-04-07 08:28:46Z murrayc $ */
7 /* Copyright 2002 The gtkmm Development Team
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 /** RefPtr<> is a reference-counting shared smartpointer.
30 * Some objects in gtkmm are obtained from a shared
31 * store. Consequently you cannot instantiate them yourself. Instead they
32 * return a RefPtr which behaves much like an ordinary pointer in that members
33 * can be reached with the usual <code>object_ptr->member</code> notation.
34 * Unlike most other smart pointers, RefPtr doesn't support dereferencing
35 * through <code>*object_ptr</code>.
37 * Reference counting means that a shared reference count is incremented each
38 * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
39 * for instance when it leaves its scope. When the reference count reaches
40 * zero, the contained object is deleted, meaning you don't need to remember
41 * to delete the object.
43 * RefPtr<> can store any class that has reference() and unreference() methods.
44 * In gtkmm, that is anything derived from Glib::ObjectBase, such as
47 * See the "Memory Management" section in the "Programming with gtkmm"
48 * book for further information.
50 template <class T_CppObject>
54 /** Default constructor
56 * Afterwards it will be null and use of -> will cause a segmentation fault.
60 /// Destructor - decrements reference count.
63 /// For use only by the ::create() methods.
64 explicit inline RefPtr(T_CppObject* pCppObject);
68 * This increments the shared reference count.
70 inline RefPtr(const RefPtr<T_CppObject>& src);
72 /** Copy constructor (from different, but castable type).
74 * Increments the reference count.
76 template <class T_CastFrom>
77 inline RefPtr(const RefPtr<T_CastFrom>& src);
79 /** Swap the contents of two RefPtr<>.
80 * This method swaps the internal pointers to T_CppObject. This can be
81 * done safely without involving a reference/unreference cycle and is
82 * therefore highly efficient.
84 inline void swap(RefPtr<T_CppObject>& other);
86 /// Copy from another RefPtr:
87 inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
89 /** Copy from different, but castable type).
91 * Increments the reference count.
93 template <class T_CastFrom>
94 inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
96 /// Tests whether the RefPtr<> point to the same underlying instance.
97 inline bool operator==(const RefPtr<T_CppObject>& src) const;
100 inline bool operator!=(const RefPtr<T_CppObject>& src) const;
104 * Use the methods of the underlying instance like so:
105 * <code>refptr->memberfun()</code>.
107 inline T_CppObject* operator->() const;
109 /** Test whether the RefPtr<> points to any underlying instance.
111 * Mimics usage of ordinary pointers:
117 inline operator bool() const;
119 /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
123 /** Dynamic cast to derived class.
125 * The RefPtr can't be cast with the usual notation so instead you can use
127 * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
130 template <class T_CastFrom>
131 static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
133 /** Static cast to derived class.
135 * Like the dynamic cast; the notation is
137 * ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
140 template <class T_CastFrom>
141 static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
143 /** Cast to non-const.
145 * The RefPtr can't be cast with the usual notation so instead you can use
147 * ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
150 template <class T_CastFrom>
151 static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
154 T_CppObject* pCppObject_;
158 #ifndef DOXYGEN_SHOULD_SKIP_THIS
160 // RefPtr<>::operator->() comes first here since it's used by other methods.
161 // If it would come after them it wouldn't be inlined.
163 template <class T_CppObject> inline
164 T_CppObject* RefPtr<T_CppObject>::operator->() const
169 template <class T_CppObject> inline
170 RefPtr<T_CppObject>::RefPtr()
175 template <class T_CppObject> inline
176 RefPtr<T_CppObject>::~RefPtr()
179 pCppObject_->unreference(); // This could cause pCppObject to be deleted.
182 template <class T_CppObject> inline
183 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
185 pCppObject_ (pCppObject)
188 template <class T_CppObject> inline
189 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
191 pCppObject_ (src.pCppObject_)
194 pCppObject_->reference();
197 // The templated ctor allows copy construction from any object that's
198 // castable. Thus, it does downcasts:
199 // base_ref = derived_ref
200 template <class T_CppObject>
201 template <class T_CastFrom>
203 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
205 // A different RefPtr<> will not allow us access to pCppObject_. We need
206 // to add a get_underlying() for this, but that would encourage incorrect
207 // use, so we use the less well-known operator->() accessor:
208 pCppObject_ (src.operator->())
211 pCppObject_->reference();
214 template <class T_CppObject> inline
215 void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
217 T_CppObject *const temp = pCppObject_;
218 pCppObject_ = other.pCppObject_;
219 other.pCppObject_ = temp;
222 template <class T_CppObject> inline
223 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
225 // In case you haven't seen the swap() technique to implement copy
226 // assignment before, here's what it does:
228 // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
229 // increasing the reference count of the source object.
231 // 2) Swap the internal object pointers of *this and the temporary
232 // RefPtr<>. After this step, *this already contains the new pointer,
233 // and the old pointer is now managed by temp.
235 // 3) The destructor of temp is executed, thereby unreferencing the
236 // old object pointer.
238 // This technique is described in Herb Sutter's "Exceptional C++", and
239 // has a number of advantages over conventional approaches:
241 // - Code reuse by calling the copy ctor.
242 // - Strong exception safety for free.
243 // - Self assignment is handled implicitely.
245 // - It just works and is hard to get wrong; i.e. you can use it without
246 // even thinking about it to implement copy assignment whereever the
247 // object data is managed indirectly via a pointer, which is very common.
249 RefPtr<T_CppObject> temp (src);
254 template <class T_CppObject>
255 template <class T_CastFrom>
257 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
259 RefPtr<T_CppObject> temp (src);
264 template <class T_CppObject> inline
265 bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
267 return (pCppObject_ == src.pCppObject_);
270 template <class T_CppObject> inline
271 bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
273 return (pCppObject_ != src.pCppObject_);
276 template <class T_CppObject> inline
277 RefPtr<T_CppObject>::operator bool() const
279 return (pCppObject_ != 0);
282 template <class T_CppObject> inline
283 void RefPtr<T_CppObject>::clear()
285 RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
289 template <class T_CppObject>
290 template <class T_CastFrom>
292 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
294 T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
297 pCppObject->reference();
299 return RefPtr<T_CppObject>(pCppObject);
302 template <class T_CppObject>
303 template <class T_CastFrom>
305 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
307 T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
310 pCppObject->reference();
312 return RefPtr<T_CppObject>(pCppObject);
315 template <class T_CppObject>
316 template <class T_CastFrom>
318 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
320 T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
323 pCppObject->reference();
325 return RefPtr<T_CppObject>(pCppObject);
328 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
330 /** @relates Glib::RefPtr */
331 template <class T_CppObject> inline
332 void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
340 #endif /* _GLIBMM_REFPTR_H */