Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

refptr.h

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 #ifndef _cairo_REFPTR_H
00003 #define _cairo_REFPTR_H
00004 
00005 /* $Id: refptr.h,v 1.3 2006/03/06 17:55:51 jjongsma Exp $ */
00006 
00007 /* Copyright 2005 The cairomm Development Team
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00022  * 02110-1301, USA.
00023  */
00024 
00025 
00026 namespace Cairo
00027 {
00028 
00046 template <class T_CppObject>
00047 class RefPtr
00048 {
00049 public:
00054   inline RefPtr();
00055   
00057   inline ~RefPtr();
00058 
00060   explicit inline RefPtr(T_CppObject* pCppObject);
00061 
00066   inline RefPtr(const RefPtr<T_CppObject>& src);
00067 
00072   template <class T_CastFrom>
00073   inline RefPtr(const RefPtr<T_CastFrom>& src);
00074 
00080   inline void swap(RefPtr<T_CppObject>& other);
00081 
00083   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
00084 
00089   template <class T_CastFrom>
00090   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
00091 
00093   inline bool operator==(const RefPtr<T_CppObject>& src) const;
00094   
00096   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
00097 
00103   inline T_CppObject* operator->() const;
00104 
00113   inline operator bool() const;
00114 
00116   inline void clear();
00117 
00118 
00126   template <class T_CastFrom>
00127   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00128 
00136   template <class T_CastFrom>
00137   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
00138 
00146   template <class T_CastFrom>
00147   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
00148 
00149 private:
00150   T_CppObject* pCppObject_;
00151 };
00152 
00153 
00154 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00155 
00156 // RefPtr<>::operator->() comes first here since it's used by other methods.
00157 // If it would come after them it wouldn't be inlined.
00158 
00159 template <class T_CppObject> inline
00160 T_CppObject* RefPtr<T_CppObject>::operator->() const
00161 {
00162   return pCppObject_;
00163 }
00164 
00165 template <class T_CppObject> inline
00166 RefPtr<T_CppObject>::RefPtr()
00167 :
00168   pCppObject_ (0)
00169 {}
00170 
00171 template <class T_CppObject> inline
00172 RefPtr<T_CppObject>::~RefPtr()
00173 {
00174   if(pCppObject_)
00175     pCppObject_->unreference(); // This could cause pCppObject to be deleted.
00176 }
00177 
00178 template <class T_CppObject> inline
00179 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
00180 :
00181   pCppObject_ (pCppObject)
00182 {}
00183 
00184 template <class T_CppObject> inline
00185 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00186 :
00187   pCppObject_ (src.pCppObject_)
00188 {
00189   if(pCppObject_)
00190     pCppObject_->reference();
00191 }
00192 
00193 // The templated ctor allows copy construction from any object that's
00194 // castable.  Thus, it does downcasts:
00195 //   base_ref = derived_ref
00196 template <class T_CppObject>
00197   template <class T_CastFrom>
00198 inline
00199 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00200 :
00201   // A different RefPtr<> will not allow us access to pCppObject_.  We need
00202   // to add a get_underlying() for this, but that would encourage incorrect
00203   // use, so we use the less well-known operator->() accessor:
00204   pCppObject_ (src.operator->())
00205 {
00206   if(pCppObject_)
00207     pCppObject_->reference();
00208 }
00209 
00210 template <class T_CppObject> inline
00211 void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00212 {
00213   T_CppObject *const temp = pCppObject_;
00214   pCppObject_ = other.pCppObject_;
00215   other.pCppObject_ = temp;
00216 }
00217 
00218 template <class T_CppObject> inline
00219 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00220 {
00221   // In case you haven't seen the swap() technique to implement copy
00222   // assignment before, here's what it does:
00223   //
00224   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00225   //    increasing the reference count of the source object.
00226   //
00227   // 2) Swap the internal object pointers of *this and the temporary
00228   //    RefPtr<>.  After this step, *this already contains the new pointer,
00229   //    and the old pointer is now managed by temp.
00230   //
00231   // 3) The destructor of temp is executed, thereby unreferencing the
00232   //    old object pointer.
00233   //
00234   // This technique is described in Herb Sutter's "Exceptional C++", and
00235   // has a number of advantages over conventional approaches:
00236   //
00237   // - Code reuse by calling the copy ctor.
00238   // - Strong exception safety for free.
00239   // - Self assignment is handled implicitely.
00240   // - Simplicity.
00241   // - It just works and is hard to get wrong; i.e. you can use it without
00242   //   even thinking about it to implement copy assignment whereever the
00243   //   object data is managed indirectly via a pointer, which is very common.
00244 
00245   RefPtr<T_CppObject> temp (src);
00246   this->swap(temp);
00247   return *this;
00248 }
00249 
00250 template <class T_CppObject>
00251   template <class T_CastFrom>
00252 inline
00253 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00254 {
00255   RefPtr<T_CppObject> temp (src);
00256   this->swap(temp);
00257   return *this;
00258 }
00259 
00260 template <class T_CppObject> inline
00261 bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00262 {
00263   return (pCppObject_ == src.pCppObject_);
00264 }
00265 
00266 template <class T_CppObject> inline
00267 bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00268 {
00269   return (pCppObject_ != src.pCppObject_);
00270 }
00271 
00272 template <class T_CppObject> inline
00273 RefPtr<T_CppObject>::operator bool() const
00274 {
00275   return (pCppObject_ != 0);
00276 }
00277 
00278 template <class T_CppObject> inline
00279 void RefPtr<T_CppObject>::clear()
00280 {
00281   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00282   this->swap(temp);
00283 }
00284 
00285 template <class T_CppObject>
00286   template <class T_CastFrom>
00287 inline
00288 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00289 {
00290   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
00291 
00292   if(pCppObject)
00293     pCppObject->reference();
00294 
00295   return RefPtr<T_CppObject>(pCppObject);
00296 }
00297 
00298 template <class T_CppObject>
00299   template <class T_CastFrom>
00300 inline
00301 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00302 {
00303   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
00304 
00305   if(pCppObject)
00306     pCppObject->reference();
00307 
00308   return RefPtr<T_CppObject>(pCppObject);
00309 }
00310 
00311 template <class T_CppObject>
00312   template <class T_CastFrom>
00313 inline
00314 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00315 {
00316   T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
00317 
00318   if(pCppObject)
00319     pCppObject->reference();
00320 
00321   return RefPtr<T_CppObject>(pCppObject);
00322 }
00323 
00324 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
00325 
00327 template <class T_CppObject> inline
00328 void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
00329 {
00330   lhs.swap(rhs);
00331 }
00332 
00333 } // namespace Cairo
00334 
00335 
00336 #endif /* _cairo_REFPTR_H */
00337 
00338 // vim: ts=2 sw=2 et

Generated on Tue Apr 4 20:48:32 2006 for cairomm by  doxygen 1.4.4