dune-common 2.1.1
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 
00007 #if defined HAVE_MEMORY
00008 # include <memory>
00009 #endif
00010 #if defined HAVE_TR1_MEMORY
00011 # include <tr1/memory>
00012 #endif
00013 #if defined HAVE_BOOST_SHARED_PTR_HPP
00014 # include <boost/shared_ptr.hpp>
00015 #endif
00016 
00017 #include<dune/common/nullptr.hh>
00018 #include<dune/common/typetraits.hh>
00025 namespace Dune
00026 {
00027     // A shared_ptr implementation has been found if SHARED_PTR_NAMESPACE is set at all
00028 #ifdef SHARED_PTR_NAMESPACE
00029     using SHARED_PTR_NAMESPACE :: shared_ptr;
00030 #else
00031 
00043     template<class T>
00044     class shared_ptr
00045     {
00046     public:
00052         typedef T element_type;
00053 
00057         inline shared_ptr();
00058         
00067         inline shared_ptr(T * pointer);
00068         
00081         template<class Deleter>
00082         inline shared_ptr(T * pointer, Deleter deleter);
00083         
00088         inline shared_ptr(const shared_ptr<T>& pointer);
00089         
00093         inline ~shared_ptr();
00094 
00096         inline shared_ptr& operator=(const shared_ptr<T>& pointer);
00097         
00099         inline element_type& operator*();
00100         
00102         inline element_type* operator->();
00103       
00105         inline const element_type& operator*() const;
00106         
00108         inline const element_type* operator->() const;
00109 
00111         element_type* get() const {
00112             return rep_==0 ? 0 : rep_->rep_;
00113         }
00114 
00116         inline void swap(shared_ptr& other);
00117 
00121         inline void reset();
00122 
00124         inline void reset(T* pointer);
00125 
00126         //** \brief Same as shared_ptr(pointer,deleter).swap(*this)
00127         template<class Deleter>
00128         inline void reset(T* pointer, Deleter deleter);
00129 
00131         int use_count() const;
00132 
00133     private:
00135         class PointerRep
00136         {
00137             friend class shared_ptr<element_type>;
00138         protected:
00140             int count_;
00142             element_type * rep_;
00144             PointerRep(element_type * p) : count_(1), rep_(p) {}
00146             virtual ~PointerRep() {};
00147         };
00148 
00150         template<class Deleter>
00151         class PointerRepImpl :
00152             public PointerRep
00153         {
00154             friend class shared_ptr<element_type>;
00155 
00157             PointerRepImpl(element_type * p, const Deleter& deleter) :
00158                 PointerRep(p),
00159                 deleter_(deleter)
00160             {}
00161 
00163             ~PointerRepImpl()
00164             { deleter_(this->rep_); }
00165 
00166             // store a copy of the deleter
00167             Deleter deleter_;
00168         };
00169 
00171         struct DefaultDeleter
00172         {
00173             void operator() (element_type* p) const
00174             { delete p; }
00175         };
00176 
00177 
00178         PointerRep *rep_;
00179 
00180         // Needed for the implicit conversion to "bool"
00181         typedef T* shared_ptr::PointerRep::*__unspecified_bool_type;
00182         
00183     public:
00185         operator __unspecified_bool_type() const // never throws
00186         { 
00187             return rep_ == 0 ? 0 : &shared_ptr::PointerRep::rep_; 
00188         }
00189 
00190 
00191     };
00192 
00193     template<class T>
00194     inline shared_ptr<T>::shared_ptr(T * p)
00195     {
00196         rep_ = new PointerRepImpl<DefaultDeleter>(p, DefaultDeleter());
00197     }
00198 
00199     template<class T>
00200     template<class Deleter>
00201     inline shared_ptr<T>::shared_ptr(T * p, Deleter deleter)
00202     {
00203         rep_ = new PointerRepImpl<Deleter>(p, deleter);
00204     }
00205 
00206     template<class T>
00207     inline shared_ptr<T>::shared_ptr()
00208     {
00209         rep_ = nullptr;
00210     }
00211 
00212     template<class T>
00213     inline shared_ptr<T>::shared_ptr(const shared_ptr<T>& other) : rep_(other.rep_)
00214     {
00215         if (rep_)
00216             ++(rep_->count_);
00217     }
00218 
00219     template<class T>
00220     inline shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr<T>& other)
00221     {
00222         if (other.rep_)
00223             (other.rep_->count_)++;
00224         
00225         if(rep_!=0 && --(rep_->count_)<=0) 
00226             delete rep_;
00227 
00228         rep_ = other.rep_;
00229         return *this;
00230     }
00231 
00232     template<class T>
00233     inline shared_ptr<T>::~shared_ptr()
00234     {
00235         if(rep_!=0 && --(rep_->count_)==0){
00236             delete rep_;
00237             rep_=0;
00238         }
00239     }
00240 
00241     template<class T>
00242     inline T& shared_ptr<T>::operator*()
00243     {
00244         return *(rep_->rep_);
00245     }
00246 
00247     template<class T>
00248     inline T *shared_ptr<T>::operator->()
00249     {
00250         return rep_->rep_;
00251     }
00252 
00253     template<class T>
00254     inline const T& shared_ptr<T>::operator*() const
00255     {
00256         return *(rep_->rep_);
00257     }
00258 
00259     template<class T>
00260     inline const T *shared_ptr<T>::operator->() const
00261     {
00262         return rep_->rep_;
00263     }
00264     
00265     template<class T>
00266     inline int shared_ptr<T>::use_count() const
00267     {
00268         return rep_->count_;
00269     }
00270 
00271     template<class T>
00272     inline void shared_ptr<T>::swap(shared_ptr<T>& other)
00273     {
00274         PointerRep* dummy = rep_;
00275         rep_ = other.rep_;
00276         other.rep_ = dummy;
00277     }
00278 
00279     template<class T>
00280     inline void shared_ptr<T>::reset()
00281     {
00282         shared_ptr<T>().swap(*this);
00283     }
00284 
00285     template<class T>
00286     inline void shared_ptr<T>::reset(T* pointer)
00287     {
00288         shared_ptr<T>(pointer).swap(*this);
00289     }
00290 
00291     template<class T>
00292     template<class Deleter>
00293     inline void shared_ptr<T>::reset(T* pointer, Deleter deleter)
00294     {
00295         shared_ptr<T>(pointer, deleter).swap(*this);
00296     }
00297 
00299 #endif  // #ifdef SHARED_PTR_NAMESPACE
00300 
00329     template<class T>
00330     struct null_deleter
00331     {
00332         void operator() (T* p) const {}
00333     };
00334 
00343     template<typename T>
00344     inline shared_ptr<T> stackobject_to_shared_ptr(T & t)
00345     {
00346         return shared_ptr<T>(&t, null_deleter<T>());
00347     }
00348 
00362     template<typename T, typename T2>
00363     inline shared_ptr<T2> stackobject_to_shared_ptr(T & t)
00364     {
00365         return shared_ptr<T2>(dynamic_cast<T2*>(&t), null_deleter<T2>());
00366     }
00367 
00368 }
00369 #endif