dune-common
2.2.0
|
00001 // $Id: smartpointer.hh 5504 2009-04-08 13:35:31Z christi $ 00002 00003 #ifndef DUNE_SHARED_PTR_HH 00004 #define DUNE_SHARED_PTR_HH 00005 00006 #if defined SHARED_PTR_HEADER 00007 # include SHARED_PTR_HEADER 00008 #endif 00009 #if defined HAVE_BOOST_SHARED_PTR_HPP 00010 #if defined HAVE_BOOST_MAKE_SHARED_HPP 00011 # include <boost/make_shared.hpp> 00012 #endif 00013 #endif 00014 00015 #include<dune/common/nullptr.hh> 00016 #include<dune/common/typetraits.hh> 00023 namespace Dune 00024 { 00025 // A shared_ptr implementation has been found if SHARED_PTR_NAMESPACE is set at all 00026 #ifdef SHARED_PTR_NAMESPACE 00027 using SHARED_PTR_NAMESPACE :: shared_ptr; 00028 #else 00029 00041 template<class T> 00042 class shared_ptr 00043 { 00044 public: 00050 typedef T element_type; 00051 00055 inline shared_ptr(); 00056 00065 inline shared_ptr(T * pointer); 00066 00079 template<class Deleter> 00080 inline shared_ptr(T * pointer, Deleter deleter); 00081 00086 inline shared_ptr(const shared_ptr<T>& pointer); 00087 00091 inline ~shared_ptr(); 00092 00094 inline shared_ptr& operator=(const shared_ptr<T>& pointer); 00095 00097 inline element_type& operator*(); 00098 00100 inline element_type* operator->(); 00101 00103 inline const element_type& operator*() const; 00104 00106 inline const element_type* operator->() const; 00107 00109 element_type* get() const { 00110 return rep_==0 ? 0 : rep_->rep_; 00111 } 00112 00114 inline void swap(shared_ptr& other); 00115 00119 inline void reset(); 00120 00122 inline void reset(T* pointer); 00123 00124 //** \brief Same as shared_ptr(pointer,deleter).swap(*this) 00125 template<class Deleter> 00126 inline void reset(T* pointer, Deleter deleter); 00127 00129 int use_count() const; 00130 00131 private: 00133 class PointerRep 00134 { 00135 friend class shared_ptr<element_type>; 00136 protected: 00138 int count_; 00140 element_type * rep_; 00142 PointerRep(element_type * p) : count_(1), rep_(p) {} 00144 virtual ~PointerRep() {}; 00145 }; 00146 00148 template<class Deleter> 00149 class PointerRepImpl : 00150 public PointerRep 00151 { 00152 friend class shared_ptr<element_type>; 00153 00155 PointerRepImpl(element_type * p, const Deleter& deleter) : 00156 PointerRep(p), 00157 deleter_(deleter) 00158 {} 00159 00161 ~PointerRepImpl() 00162 { deleter_(this->rep_); } 00163 00164 // store a copy of the deleter 00165 Deleter deleter_; 00166 }; 00167 00169 struct DefaultDeleter 00170 { 00171 void operator() (element_type* p) const 00172 { delete p; } 00173 }; 00174 00175 00176 PointerRep *rep_; 00177 00178 // Needed for the implicit conversion to "bool" 00179 typedef T* shared_ptr::PointerRep::*__unspecified_bool_type; 00180 00181 public: 00183 operator __unspecified_bool_type() const // never throws 00184 { 00185 return rep_ == 0 ? 0 : &shared_ptr::PointerRep::rep_; 00186 } 00187 00188 00189 }; 00190 00191 template<class T> 00192 inline shared_ptr<T>::shared_ptr(T * p) 00193 { 00194 rep_ = new PointerRepImpl<DefaultDeleter>(p, DefaultDeleter()); 00195 } 00196 00197 template<class T> 00198 template<class Deleter> 00199 inline shared_ptr<T>::shared_ptr(T * p, Deleter deleter) 00200 { 00201 rep_ = new PointerRepImpl<Deleter>(p, deleter); 00202 } 00203 00204 template<class T> 00205 inline shared_ptr<T>::shared_ptr() 00206 { 00207 rep_ = nullptr; 00208 } 00209 00210 template<class T> 00211 inline shared_ptr<T>::shared_ptr(const shared_ptr<T>& other) : rep_(other.rep_) 00212 { 00213 if (rep_) 00214 ++(rep_->count_); 00215 } 00216 00217 template<class T> 00218 inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T>& other) 00219 { 00220 if (other.rep_) 00221 (other.rep_->count_)++; 00222 00223 if(rep_!=0 && --(rep_->count_)<=0) 00224 delete rep_; 00225 00226 rep_ = other.rep_; 00227 return *this; 00228 } 00229 00230 template<class T> 00231 inline shared_ptr<T>::~shared_ptr() 00232 { 00233 if(rep_!=0 && --(rep_->count_)==0){ 00234 delete rep_; 00235 rep_=0; 00236 } 00237 } 00238 00239 template<class T> 00240 inline T& shared_ptr<T>::operator*() 00241 { 00242 return *(rep_->rep_); 00243 } 00244 00245 template<class T> 00246 inline T *shared_ptr<T>::operator->() 00247 { 00248 return rep_->rep_; 00249 } 00250 00251 template<class T> 00252 inline const T& shared_ptr<T>::operator*() const 00253 { 00254 return *(rep_->rep_); 00255 } 00256 00257 template<class T> 00258 inline const T *shared_ptr<T>::operator->() const 00259 { 00260 return rep_->rep_; 00261 } 00262 00263 template<class T> 00264 inline int shared_ptr<T>::use_count() const 00265 { 00266 return rep_->count_; 00267 } 00268 00269 template<class T> 00270 inline void shared_ptr<T>::swap(shared_ptr<T>& other) 00271 { 00272 PointerRep* dummy = rep_; 00273 rep_ = other.rep_; 00274 other.rep_ = dummy; 00275 } 00276 00277 template<class T> 00278 inline void shared_ptr<T>::reset() 00279 { 00280 shared_ptr<T>().swap(*this); 00281 } 00282 00283 template<class T> 00284 inline void shared_ptr<T>::reset(T* pointer) 00285 { 00286 shared_ptr<T>(pointer).swap(*this); 00287 } 00288 00289 template<class T> 00290 template<class Deleter> 00291 inline void shared_ptr<T>::reset(T* pointer, Deleter deleter) 00292 { 00293 shared_ptr<T>(pointer, deleter).swap(*this); 00294 } 00295 00297 #endif // #ifdef SHARED_PTR_NAMESPACE 00298 00299 00300 // C++0x and Boost have a make_shared implementation, TR1 does not. 00301 // Unfortunately, TR1 gets picked over Boost if present. 00302 // Moreover, boost::make_shared() only exists for (remotely) recent versions of Boost. 00303 #if HAVE_MAKE_SHARED 00304 #ifdef SHARED_PTR_NAMESPACE 00305 using SHARED_PTR_NAMESPACE :: make_shared; 00306 #endif 00307 #else 00308 00309 template<typename T> 00310 shared_ptr<T> make_shared() 00311 { 00312 return shared_ptr<T>(new T()); 00313 } 00314 00315 template<typename T, typename Arg1> 00316 shared_ptr<T> make_shared(const Arg1& arg1) 00317 { 00318 return shared_ptr<T>(new T(arg1)); 00319 } 00320 00321 template<typename T, typename Arg1, typename Arg2> 00322 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2) 00323 { 00324 return shared_ptr<T>(new T(arg1,arg2)); 00325 } 00326 00327 template<typename T, typename Arg1, typename Arg2, typename Arg3> 00328 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) 00329 { 00330 return shared_ptr<T>(new T(arg1,arg2,arg3)); 00331 } 00332 00333 template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> 00334 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) 00335 { 00336 return shared_ptr<T>(new T(arg1,arg2,arg3,arg4)); 00337 } 00338 00339 template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, 00340 typename Arg5> 00341 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, 00342 const Arg5& arg5) 00343 { 00344 return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5)); 00345 } 00346 00347 template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, 00348 typename Arg5, typename Arg6> 00349 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, 00350 const Arg5& arg5, const Arg6& arg6) 00351 { 00352 return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6)); 00353 } 00354 00355 template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, 00356 typename Arg5, typename Arg6, typename Arg7> 00357 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, 00358 const Arg5& arg5, const Arg6& arg6, const Arg7& arg7) 00359 { 00360 return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7)); 00361 } 00362 00363 template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, 00364 typename Arg5, typename Arg6, typename Arg7, typename Arg8> 00365 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, 00366 const Arg5& arg5, const Arg6& arg6, const Arg7& arg7, const Arg8& arg8) 00367 { 00368 return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)); 00369 } 00370 00371 template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, 00372 typename Arg5, typename Arg6, typename Arg7, typename Arg8, typename Arg9> 00373 shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, 00374 const Arg5& arg5, const Arg6& arg6, const Arg7& arg7, const Arg8& arg8, 00375 const Arg9& arg9) 00376 { 00377 return shared_ptr<T>(new T(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)); 00378 } 00379 00380 #endif // custom make_shared 00381 00410 template<class T> 00411 struct null_deleter 00412 { 00413 void operator() (T* p) const {} 00414 }; 00415 00424 template<typename T> 00425 inline shared_ptr<T> stackobject_to_shared_ptr(T & t) 00426 { 00427 return shared_ptr<T>(&t, null_deleter<T>()); 00428 } 00429 00443 template<typename T, typename T2> 00444 inline shared_ptr<T2> stackobject_to_shared_ptr(T & t) 00445 { 00446 return shared_ptr<T2>(dynamic_cast<T2*>(&t), null_deleter<T2>()); 00447 } 00448 00449 } 00450 #endif