dune-common  2.2.0
shared_ptr.hh
Go to the documentation of this file.
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