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.1 2005/12/20 09:17:53 murrayc 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
00021  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022  */
00023 
00024 
00025 namespace Cairo
00026 {
00027 
00045 template <class T_CppObject>
00046 class RefPtr
00047 {
00048 public:
00053   inline RefPtr();
00054   
00056   inline ~RefPtr();
00057 
00059   explicit inline RefPtr(T_CppObject* pCppObject);
00060 
00065   inline RefPtr(const RefPtr<T_CppObject>& src);
00066 
00071   template <class T_CastFrom>
00072   inline RefPtr(const RefPtr<T_CastFrom>& src);
00073 
00079   inline void swap(RefPtr<T_CppObject>& other);
00080 
00082   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
00083 
00088   template <class T_CastFrom>
00089   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
00090 
00092   inline bool operator==(const RefPtr<T_CppObject>& src) const;
00093   
00095   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
00096 
00102   inline T_CppObject* operator->() const;
00103 
00112   inline operator bool() const;
00113 
00115   inline void clear();
00116 
00117 
00125   template <class T_CastFrom>
00126   static inline RefPtr<T_CppObject> cast_dynamic(const RefPtr<T_CastFrom>& src);
00127 
00135   template <class T_CastFrom>
00136   static inline RefPtr<T_CppObject> cast_static(const RefPtr<T_CastFrom>& src);
00137 
00145   template <class T_CastFrom>
00146   static inline RefPtr<T_CppObject> cast_const(const RefPtr<T_CastFrom>& src);
00147 
00148 private:
00149   T_CppObject* pCppObject_;
00150 };
00151 
00152 
00153 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00154 
00155 // RefPtr<>::operator->() comes first here since it's used by other methods.
00156 // If it would come after them it wouldn't be inlined.
00157 
00158 template <class T_CppObject> inline
00159 T_CppObject* RefPtr<T_CppObject>::operator->() const
00160 {
00161   return pCppObject_;
00162 }
00163 
00164 template <class T_CppObject> inline
00165 RefPtr<T_CppObject>::RefPtr()
00166 :
00167   pCppObject_ (0)
00168 {}
00169 
00170 template <class T_CppObject> inline
00171 RefPtr<T_CppObject>::~RefPtr()
00172 {
00173   if(pCppObject_)
00174     pCppObject_->unreference(); // This could cause pCppObject to be deleted.
00175 }
00176 
00177 template <class T_CppObject> inline
00178 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
00179 :
00180   pCppObject_ (pCppObject)
00181 {}
00182 
00183 template <class T_CppObject> inline
00184 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
00185 :
00186   pCppObject_ (src.pCppObject_)
00187 {
00188   if(pCppObject_)
00189     pCppObject_->reference();
00190 }
00191 
00192 // The templated ctor allows copy construction from any object that's
00193 // castable.  Thus, it does downcasts:
00194 //   base_ref = derived_ref
00195 template <class T_CppObject>
00196   template <class T_CastFrom>
00197 inline
00198 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CastFrom>& src)
00199 :
00200   // A different RefPtr<> will not allow us access to pCppObject_.  We need
00201   // to add a get_underlying() for this, but that would encourage incorrect
00202   // use, so we use the less well-known operator->() accessor:
00203   pCppObject_ (src.operator->())
00204 {
00205   if(pCppObject_)
00206     pCppObject_->reference();
00207 }
00208 
00209 template <class T_CppObject> inline
00210 void RefPtr<T_CppObject>::swap(RefPtr<T_CppObject>& other)
00211 {
00212   T_CppObject *const temp = pCppObject_;
00213   pCppObject_ = other.pCppObject_;
00214   other.pCppObject_ = temp;
00215 }
00216 
00217 template <class T_CppObject> inline
00218 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CppObject>& src)
00219 {
00220   // In case you haven't seen the swap() technique to implement copy
00221   // assignment before, here's what it does:
00222   //
00223   // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
00224   //    increasing the reference count of the source object.
00225   //
00226   // 2) Swap the internal object pointers of *this and the temporary
00227   //    RefPtr<>.  After this step, *this already contains the new pointer,
00228   //    and the old pointer is now managed by temp.
00229   //
00230   // 3) The destructor of temp is executed, thereby unreferencing the
00231   //    old object pointer.
00232   //
00233   // This technique is described in Herb Sutter's "Exceptional C++", and
00234   // has a number of advantages over conventional approaches:
00235   //
00236   // - Code reuse by calling the copy ctor.
00237   // - Strong exception safety for free.
00238   // - Self assignment is handled implicitely.
00239   // - Simplicity.
00240   // - It just works and is hard to get wrong; i.e. you can use it without
00241   //   even thinking about it to implement copy assignment whereever the
00242   //   object data is managed indirectly via a pointer, which is very common.
00243 
00244   RefPtr<T_CppObject> temp (src);
00245   this->swap(temp);
00246   return *this;
00247 }
00248 
00249 template <class T_CppObject>
00250   template <class T_CastFrom>
00251 inline
00252 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
00253 {
00254   RefPtr<T_CppObject> temp (src);
00255   this->swap(temp);
00256   return *this;
00257 }
00258 
00259 template <class T_CppObject> inline
00260 bool RefPtr<T_CppObject>::operator==(const RefPtr<T_CppObject>& src) const
00261 {
00262   return (pCppObject_ == src.pCppObject_);
00263 }
00264 
00265 template <class T_CppObject> inline
00266 bool RefPtr<T_CppObject>::operator!=(const RefPtr<T_CppObject>& src) const
00267 {
00268   return (pCppObject_ != src.pCppObject_);
00269 }
00270 
00271 template <class T_CppObject> inline
00272 RefPtr<T_CppObject>::operator bool() const
00273 {
00274   return (pCppObject_ != 0);
00275 }
00276 
00277 template <class T_CppObject> inline
00278 void RefPtr<T_CppObject>::clear()
00279 {
00280   RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
00281   this->swap(temp);
00282 }
00283 
00284 template <class T_CppObject>
00285   template <class T_CastFrom>
00286 inline
00287 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
00288 {
00289   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
00290 
00291   if(pCppObject)
00292     pCppObject->reference();
00293 
00294   return RefPtr<T_CppObject>(pCppObject);
00295 }
00296 
00297 template <class T_CppObject>
00298   template <class T_CastFrom>
00299 inline
00300 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
00301 {
00302   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
00303 
00304   if(pCppObject)
00305     pCppObject->reference();
00306 
00307   return RefPtr<T_CppObject>(pCppObject);
00308 }
00309 
00310 template <class T_CppObject>
00311   template <class T_CastFrom>
00312 inline
00313 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_const(const RefPtr<T_CastFrom>& src)
00314 {
00315   T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.operator->());
00316 
00317   if(pCppObject)
00318     pCppObject->reference();
00319 
00320   return RefPtr<T_CppObject>(pCppObject);
00321 }
00322 
00323 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
00324 
00326 template <class T_CppObject> inline
00327 void swap(RefPtr<T_CppObject>& lhs, RefPtr<T_CppObject>& rhs)
00328 {
00329   lhs.swap(rhs);
00330 }
00331 
00332 } // namespace Cairo
00333 
00334 
00335 #endif /* _cairo_REFPTR_H */
00336 

Generated on Thu Feb 9 12:47:13 2006 for cairomm by  doxygen 1.4.4