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

ref.h

Go to the documentation of this file.
00001 #ifndef DV_REF_H 00002 #define DV_REF_H 00003 // $Id: ref.h,v 1.15 2003/07/14 09:15:28 dvermeir Exp $ 00004 00005 /*! \file 00006 * The Dv::ref class implements reference-counted pointers. 00007 */ 00008 00009 namespace Dv { 00010 namespace Util { 00011 //! Reference-counted pointers. 00012 /*! Example usage: 00013 00014 \code 00015 #include <iostream> 00016 #include <string> 00017 #include <dvutil/ref.h> 00018 using Dv::ref; 00019 00020 class Huge { 00021 friend class ref<Huge>; 00022 public: 00023 friend ostream& operator<<(ostream& os, const Huge& h) { 00024 return os << h._s; } 00025 const string& s() const { return _s; } 00026 static Dv::ref<Huge> create(const char *s) { 00027 return ref<Huge>(new Huge(s)); } 00028 private: 00029 string _s; 00030 Huge(const char* s): _s(s) {} 00031 ~Huge(); 00032 }; 00033 00034 int 00035 main(int argc,char *argv[]) { 00036 ref<Huge> r = Huge::create("c++"); 00037 ref<Huge> p = r; 00038 cout << *p << p->s() << endl; 00039 } 00040 \endcode 00041 */ 00042 template<class T> 00043 class ref { 00044 //! only T can produce non-null ref<T> objects. 00045 // friend T; 00046 // template<typename X> friend class ref; // does not work with gcc 2.95.3 00047 public: 00048 /** Default constructor makes null ref<T> */ 00049 ref(): t_(0), n_(new unsigned int(1)) { /* cerr << "0-CTOR" << endl; */} 00050 //! copy constructor increments reference count 00051 ref(const ref<T>& r): t_(r.operator->()), n_(r.n()) { ++*n_; } 00052 00053 template<typename X> 00054 explicit ref(const ref<X>& r): t_(r.operator->()), n_(r.n()) { ++*n_; } 00055 //! destructor decrements reference count or deletes underlying pointer 00056 ~ref() { if (--*n_) return; delete t_; delete n_; } 00057 00058 //! return pointer to counter 00059 // should be private but gcc 2.95.3 does not accept template<typename X> friend class ref; 00060 unsigned int* n() const { return n_; } 00061 //! is this a null ref<T>? 00062 operator bool() const { return (t_!=0); } 00063 //! ref<T> objects can be dereferenced like a pointer 00064 T& operator*() const { return *t_; } 00065 //! ref<T> objects support -> like pointers 00066 T* operator->() const { return t_; } 00067 //! assignment decrements reference count of lhs, increases count for rhs 00068 ref<T>& operator=(const ref<T>& r) { 00069 if (this==&r) return *this; 00070 if (--*n_==0) { delete t_; delete n_; } 00071 t_ = r.t_; 00072 n_=r.n_; 00073 ++*n_; 00074 return *this; 00075 } 00076 //! == compares underlying T objects 00077 bool operator==(const ref<T>& r) const { 00078 if (t_ == r.t_) return true; 00079 if (t_) 00080 if (r.t_) 00081 return (*t_ == *r); 00082 else 00083 return false; 00084 // r.t_ != t_ == 0 00085 return false; 00086 } 00087 //! < compares underlying T objects 00088 bool operator<(const ref<T>& r) const { 00089 // null is minimal element in this implementation 00090 if (t_ == r.t_) return false; 00091 if (t_) 00092 if (r.t_) 00093 return (*t_ < *r); 00094 else 00095 return false; 00096 // t_ == 0, r.t_ != 0 00097 return true; 00098 } 00099 // protected: 00100 //! only T objects can encapsulate a (new'ed) pointer into a ref<T> 00101 // template<typename X> 00102 explicit ref(T* t): t_(t), n_(new unsigned int(1)) {} 00103 00104 template<typename X> 00105 operator ref<X>() const { return ref<X>(*this); } 00106 00107 private: 00108 00109 T* t_; 00110 unsigned int* n_; 00111 }; 00112 }} 00113 00114 #endif

dvutil-0.13.15 [30 December, 2004]