00001
00002
00003
00004
00005
00006
00007 #ifndef SMARTPOINTER_H
00008 #define SMARTPOINTER_H
00009
00010 #if defined(_MSC_VER)
00011 # define for if(0);else for
00012 # pragma warning(disable:4786)
00013 # pragma warning(disable:4521)
00014 # pragma warning(disable:4522)
00015 # pragma warning(disable:4355)
00016 # pragma warning(disable:4291)
00017 #endif
00018
00019 #include <algorithm>
00020 #include <cassert>
00021 #include <stdexcept>
00022 #include <cassert>
00023
00024 template <bool> struct StaticAssert;
00025 template <> struct StaticAssert<true> {};
00026 template <class T> struct is_void {enum {result = 0};};
00027 template <> struct is_void<void> {enum {result = 1};};
00028
00029
00030
00031
00032
00033 template<class T>
00034 struct PointerTraits_
00035 {
00036 StaticAssert<!is_void<T>::result> Error_Smart_Pointer_Does_Not_Support_Void_Ptr;
00037 typedef T ValueType;
00038 typedef T& ReferenceType;
00039 typedef const T& ConstReferenceType;
00040 typedef T* PointerType;
00041 typedef const T* ConstPointerType;
00042 static const PointerType Null;
00043
00044 static void freeResource(PointerType p)
00045 {
00046 enum { no_incomplete_types_please = sizeof(*p) };
00047 delete p;
00048 }
00049 };
00050
00051 template<class T>
00052 const typename PointerTraits_<T>::PointerType PointerTraits_<T>::Null = 0;
00053
00054
00055 template<class T>
00056 struct ArrayPointerTraits_
00057 {
00058 typedef T ValueType;
00059 typedef T& ReferenceType;
00060 typedef const T& ConstReferenceType;
00061 typedef T* PointerType;
00062 typedef const T* ConstPointerType;
00063 static const PointerType Null;
00064
00065 static void freeResource(PointerType p)
00066 {
00067 delete [] p;
00068 }
00069 };
00070
00071 template<class T>
00072 const typename ArrayPointerTraits_<T>::PointerType ArrayPointerTraits_<T>::Null = 0;
00073
00074 template<class Traits>
00075 class SingleOwner_
00076 {
00077 public:
00078 typedef typename Traits::PointerType PT;
00079 typedef typename Traits::ConstPointerType CPT;
00080 static CPT null() { return Traits::Null; }
00081 private:
00082 PT managed_;
00083
00084 SingleOwner_(const SingleOwner_&);
00085 SingleOwner_& operator=(const SingleOwner_&);
00086 public:
00087 ~SingleOwner_()
00088 {
00089 Traits::freeResource(managed_);
00090 }
00091 explicit
00092 SingleOwner_()
00093 : managed_(Traits::Null)
00094 {}
00095 explicit
00096 SingleOwner_(PT p)
00097 : managed_(p)
00098 {}
00099
00100 SingleOwner_(SingleOwner_& o)
00101 : managed_(Traits::Null)
00102 {
00103 swap(o);
00104 }
00105
00106 SingleOwner_& operator=(SingleOwner_& o)
00107 {
00108 swap(o);
00109 return *this;
00110 }
00111 SingleOwner_& operator=(PT p)
00112 {
00113 SingleOwner_().swap(*this);
00114 managed_ = p;
00115 return *this;
00116 }
00117 bool unique() const { return true; }
00118 size_t count() const { return 1; }
00119 PT get() { return managed_; }
00120 CPT get() const { return managed_; }
00121 void swap(SingleOwner_& o)
00122 {
00123 std::swap(managed_, o.managed_);
00124 }
00125 void reset()
00126 {
00127 SingleOwner_().swap(*this);
00128 }
00129 void release()
00130 {
00131 managed_ = Traits::Null;
00132 }
00133 };
00134
00135 template<class Traits>
00136 class ReferenceCountedOwner_
00137 {
00138 public:
00139 typedef typename Traits::PointerType PT;
00140 typedef typename Traits::ConstPointerType CPT;
00141 static CPT null() { return Traits::Null; }
00142 private:
00143 class RefCount_
00144 {
00145 PT managed_;
00146 size_t count_;
00147 RefCount_();
00148 RefCount_(const RefCount_&);
00149 RefCount_& operator=(const RefCount_&);
00150 public:
00151 explicit
00152 RefCount_(PT p)
00153 : managed_(p)
00154 , count_(1)
00155 {}
00156 void inc()
00157 {
00158 ++count_;
00159 }
00160 size_t count() const { return count_; }
00161 bool unique() const { return count_ == 1; }
00162 void dec()
00163 {
00164 --count_;
00165 if(!count_)
00166 {
00167 PT deleteme = managed_;
00168 delete this;
00169 Traits::freeResource(deleteme);
00170 }
00171
00172 }
00173 void weakDec()
00174 {
00175 --count_;
00176 if(!count_)
00177 {
00178 delete this;
00179 }
00180 }
00181 PT get() { return managed_; }
00182 CPT get() const { return managed_; }
00183 };
00184 RefCount_* refCount_;
00185
00186 void decIfValidRefCount()
00187 {
00188 if(refCount_)
00189 {
00190 RefCount_* temp = 0;
00191 std::swap(temp, refCount_);
00192 temp->dec();
00193 }
00194
00195 }
00196 void incIfValidRefCount()
00197 {
00198 if(refCount_)
00199 refCount_->inc();
00200 }
00201 static RefCount_* createRefCount(PT p)
00202 {
00203 return p == Traits::Null ? 0 : new RefCount_(p);
00204 }
00205 public:
00206 ~ReferenceCountedOwner_()
00207 {
00208 decIfValidRefCount();
00209 }
00210 explicit
00211 ReferenceCountedOwner_()
00212 : refCount_(0)
00213 {}
00214 ReferenceCountedOwner_(PT p)
00215 : refCount_(createRefCount(p))
00216 {}
00217 ReferenceCountedOwner_(const ReferenceCountedOwner_& o)
00218 : refCount_(o.refCount_)
00219 {
00220 incIfValidRefCount();
00221 }
00222 ReferenceCountedOwner_& operator=(const ReferenceCountedOwner_& o)
00223 {
00224 ReferenceCountedOwner_().swap(*this);
00225
00226 refCount_ = o.refCount_;
00227 incIfValidRefCount();
00228
00229 return *this;
00230 }
00231 ReferenceCountedOwner_& operator=(PT p)
00232 {
00233 ReferenceCountedOwner_().swap(*this);
00234 refCount_ = createRefCount(p);
00235
00236 return *this;
00237 }
00238 bool unique() const { return refCount_ ? refCount_->unique() : true; }
00239 size_t count() const { return refCount_ ? refCount_->count() : 1; }
00240 PT get() { return refCount_ ? refCount_->get() : Traits::Null; }
00241 CPT get() const { return refCount_ ? refCount_->get() : Traits::Null; }
00242 void swap(ReferenceCountedOwner_& o)
00243 {
00244 std::swap(refCount_, o.refCount_);
00245 }
00246 void reset()
00247 {
00248 ReferenceCountedOwner_().swap(*this);
00249 }
00250 void release()
00251 {
00252 if(refCount_)
00253 refCount_->weakDec();
00254 refCount_ = 0;
00255 }
00256 };
00257
00258 template
00259 <
00260 class T,
00261 class Traits = PointerTraits_<T>,
00262 class RefCountPolicy = SingleOwner_<Traits>
00263 >
00264 class SmartPointer : public RefCountPolicy
00265 {
00266 public:
00267 typedef typename Traits::ValueType VT;
00268 typedef typename Traits::PointerType PT;
00269 typedef typename Traits::ConstPointerType CPT;
00270 typedef typename Traits::ReferenceType RT;
00271 typedef typename Traits::ConstReferenceType CRT;
00272
00273 explicit
00274 SmartPointer()
00275 {}
00276 explicit
00277 SmartPointer(PT p)
00278 : RefCountPolicy(p)
00279 {}
00280
00281 SmartPointer(const SmartPointer& o)
00282 : RefCountPolicy(o)
00283 {}
00284 SmartPointer(SmartPointer& o)
00285 : RefCountPolicy(o)
00286 {}
00287 SmartPointer& operator=(SmartPointer& o)
00288 {
00289 RefCountPolicy::operator=(o);
00290 return *this;
00291 }
00292 SmartPointer& operator=(const SmartPointer& o)
00293 {
00294 RefCountPolicy::operator=(o);
00295 return *this;
00296 }
00297 SmartPointer& operator=(PT p)
00298 {
00299 RefCountPolicy::operator=(p);
00300 return *this;
00301 }
00302 bool operator==(const SmartPointer& o) const
00303 {
00304 return this->get() == o.get();
00305 }
00306 bool operator!=(const SmartPointer& o) const
00307 {
00308 return this->get() != o.get();
00309 }
00310
00311 operator bool() const { return this->get() != Traits::Null; }
00312 PT operator->() { return this->get(); }
00313 CPT operator->() const { return this->get(); }
00314 RT operator*() { return *this->get(); }
00315 CRT operator*() const { return *this->get(); }
00316 };
00317
00318 template<class T, class Traits = PointerTraits_<T> >
00319 class SharedPtr : public SmartPointer<T, Traits, ReferenceCountedOwner_<Traits> >
00320 {
00321 typedef SmartPointer<T, Traits, ReferenceCountedOwner_<Traits> > Base;
00322 public:
00323 typedef typename Base::PT PT;
00324 typedef typename Base::VT VT;
00325 explicit
00326 SharedPtr()
00327 : Base()
00328 {}
00329
00330 SharedPtr(PT p)
00331 : Base(p)
00332 {}
00333 SharedPtr(const SharedPtr& o)
00334 : Base(o)
00335 {}
00336 SharedPtr& operator=(PT p) {
00337 Base::operator=(p);
00338 return *this;
00339 }
00340 };
00341
00342
00343 #endif