libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/pointer.hpp
Go to the documentation of this file.
00001 
00011 /*
00012  *  Copyright (C) 2008, 2009 Juan Pedro BolĂ­var Puente
00013  *
00014  *  This file is part of Psychosynth.
00015  *   
00016  *  Psychosynth is free software: you can redistribute it and/or modify
00017  *  it under the terms of the GNU General Public License as published by
00018  *  the Free Software Foundation, either version 3 of the License, or
00019  *  (at your option) any later version.
00020  *
00021  *  Psychosynth is distributed in the hope that it will be useful,
00022  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024  *  GNU General Public License for more details.
00025  *
00026  *  You should have received a copy of the GNU General Public License
00027  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 #ifndef PSYNTH_POINTER_HPP
00032 #define PSYNTH_POINTER_HPP
00033 
00034 #include <memory>
00035 #include <algorithm>
00036 
00037 namespace psynth
00038 {
00039 namespace base
00040 {
00041 
00046 template <class PtrT>
00047 struct deleter
00048 {
00049     void operator () (PtrT ptr)
00050     {
00051         delete ptr;
00052     }
00053 };
00054 
00055 template <class T>
00056 class null_ptr
00057 {
00058 public:
00059     null_ptr ()
00060         : m_ptr (0)
00061     {}
00062 
00063     null_ptr (null_ptr& p)
00064         : m_ptr (p.m_ptr)
00065     {}
00066     
00067     template <class Y>
00068     null_ptr (null_ptr<Y>& p)
00069         : m_ptr (p.m_ptr)
00070     {}
00071     
00072     null_ptr (T* ptr)
00073         : m_ptr (ptr)
00074     {}
00075     
00076     template <class Y>
00077     null_ptr (Y* ptr)
00078         : m_ptr (ptr)
00079     {}
00080 
00081     T* operator-> () const
00082     {
00083         return m_ptr;
00084     }
00085     
00086     T& operator* () const
00087     {
00088         return *m_ptr;
00089     }
00090 
00091     operator T* () const
00092     {
00093         return m_ptr;
00094     }
00095 
00096     operator bool () const
00097     {
00098         return m_ptr != 0;
00099     }
00100 
00101 private:
00102     T* m_ptr;
00103 };
00104 
00105 template <class T>
00106 class mgr_ptr;
00107 
00108 template <class T>
00109 class mgr_auto_ptr;
00110 
00111 template <class T>
00112 class manage_me_ptr
00113 {
00114     template <class Y> friend class mgr_ptr;
00115     template <class Y> friend class mgr_auto_ptr;
00116     
00117     T* m_ptr;
00118 public:
00119 
00120     manage_me_ptr (T* p)
00121         : m_ptr (p)
00122     {}
00123 };
00124 
00125 template <class T>
00126 class mgr_ptr
00127 {
00128     T* m_ptr;
00129     bool m_managed;
00130     
00131 public:
00132     ~mgr_ptr () { }
00133     
00134     mgr_ptr ()
00135         : m_ptr (0)
00136         , m_managed (false) {}
00137 
00138     mgr_ptr (const mgr_ptr& p)
00139         : m_ptr (p.m_ptr)
00140         , m_managed (p.m_managed)
00141     {}
00142     
00143     template <class Y>
00144     mgr_ptr (const mgr_ptr<Y>& p)
00145         : m_ptr (p.m_ptr)
00146         , m_managed (p.m_managed)
00147     {}
00148     
00149     mgr_ptr (T* ptr)
00150         : m_ptr (ptr)
00151         , m_managed (false)
00152     {}
00153     
00154     template <class Y>
00155     mgr_ptr (Y* ptr)
00156         : m_ptr (ptr)
00157         , m_managed (false)
00158     {}
00159     
00160     template <class Y>
00161     mgr_ptr (const manage_me_ptr<Y>& p)
00162         : m_ptr (p.m_ptr)
00163         , m_managed (true)
00164     {}
00165 
00166     mgr_ptr& operator= (const mgr_ptr& p)
00167     {
00168         m_ptr = p.m_ptr;
00169         m_managed = p.m_managed;
00170         return *this;
00171     }
00172     
00173     template <class Y>
00174     mgr_ptr& operator= (const mgr_ptr<Y>& p)
00175     {
00176         m_ptr = p.m_ptr;
00177         m_managed = p.m_managed;
00178         return *this;
00179     }
00180 
00181     mgr_ptr& operator= (T* p)
00182     {
00183         m_ptr = p;
00184         m_managed = false;
00185         return *this;
00186     }
00187     
00188     template <class Y>
00189     mgr_ptr& operator= (Y* p)
00190     {
00191         m_ptr = p;
00192         m_managed = false;
00193         return *this;
00194     }
00195 
00196     template <class Y>
00197     mgr_ptr& operator= (const manage_me_ptr<Y>& p)
00198     {
00199         m_ptr = p.m_ptr;
00200         m_managed = true;
00201         return *this;
00202     }
00203 
00204     T* operator-> () const
00205     {
00206         return m_ptr;
00207     }
00208     
00209     T& operator* () const
00210     {
00211         return *m_ptr;
00212     }
00213 
00214     operator T* () const
00215     {
00216         return m_ptr;
00217     }
00218 
00219     operator bool () const
00220     {
00221         return m_ptr != 0;
00222     }
00223     
00224     T* get () const
00225     {
00226         return m_ptr;
00227     }
00228 
00229     bool is_managed () const
00230     {
00231         return m_managed;
00232     }
00233     
00234     void manage ()
00235     {
00236         m_managed = true;
00237     }
00238     
00239     void unmanage ()
00240     {
00241         m_managed = false;
00242     }
00243     
00244     void clean ()
00245     {
00246         if (m_managed) {
00247             delete m_ptr;
00248             m_ptr = 0;
00249         }
00250     }
00251 };
00252 
00253 template <class T>
00254 class mgr_auto_ptr
00255 {
00256     T* m_ptr;
00257     bool m_managed;
00258     
00259 public:
00260     ~mgr_auto_ptr ()
00261     {
00262         clean ();
00263     }
00264     
00265     mgr_auto_ptr ()
00266         : m_ptr (0)
00267         , m_managed (false)
00268     {}
00269 
00270     mgr_auto_ptr (mgr_auto_ptr& p)
00271         : m_ptr (p.m_ptr)
00272         , m_managed (p.m_managed)
00273     {
00274         p.unmanage ();
00275     }
00276     
00277     template <class Y>
00278     mgr_auto_ptr (mgr_auto_ptr<Y>& p)
00279         : m_ptr (p.m_ptr)
00280         , m_managed (p.m_managed)
00281     {
00282         p.unmanage ();
00283     }
00284     
00285     mgr_auto_ptr (T* ptr)
00286         : m_ptr (ptr)
00287         , m_managed (false)
00288     {}
00289     
00290     template <class Y>
00291     mgr_auto_ptr (Y* ptr)
00292         : m_ptr (ptr)
00293         , m_managed (false)
00294     {}
00295     
00296     template <class Y>
00297     mgr_auto_ptr (const manage_me_ptr<Y>& p)
00298         : m_ptr (p.m_ptr)
00299         , m_managed (true)
00300     {}
00301 
00302     template <class Y>
00303     mgr_auto_ptr (std::auto_ptr<Y>& p)
00304         : m_ptr (p.release ())
00305         , m_managed (true)
00306     {}
00307     
00308     mgr_auto_ptr& operator= (mgr_auto_ptr& p)
00309     {
00310         if (&p != this) {
00311             clean ();
00312             m_ptr = p.m_ptr;
00313             m_managed = p.m_managed;
00314             p.unmanage ();
00315         }
00316         
00317         return *this;
00318     }
00319     
00320     template <class Y>
00321     mgr_auto_ptr& operator= (mgr_auto_ptr<Y>& p)
00322     {
00323         if (&p != this) {
00324             clean ();
00325             m_ptr = p.m_ptr;
00326             m_managed = p.m_managed;
00327             p.unmanage ();
00328         }
00329         return *this;
00330     }
00331     
00332     mgr_auto_ptr& operator= (T* p)
00333     {
00334         if (p != m_ptr) {
00335             clean ();
00336             m_ptr = p;
00337             m_managed = false;
00338         }
00339         
00340         return *this;
00341     }
00342     
00343     template <class Y>
00344     mgr_auto_ptr& operator= (Y* p)
00345     {
00346         clean ();
00347         m_ptr = p;
00348         m_managed = false;
00349         return *this;
00350     }
00351 
00352     template <class Y>
00353     mgr_auto_ptr& operator= (const manage_me_ptr<Y>& p)
00354     {
00355         clean ();
00356         m_ptr = p.m_ptr;
00357         m_managed = true;
00358         return *this;
00359     }
00360 
00361     template <class Y>
00362     mgr_auto_ptr& operator= (std::auto_ptr<Y>& p)
00363     {
00364         clean ();
00365         m_ptr = p.release ();
00366         m_managed = true;
00367         return *this;
00368     }
00369     
00370     T* operator-> () const
00371     {
00372         return m_ptr;
00373     }
00374     
00375     T& operator* () const
00376     {
00377         return *m_ptr;
00378     }
00379 
00380     operator T* () const
00381     {
00382         return m_ptr;
00383     }
00384 
00385     operator bool () const
00386     {
00387         return m_ptr != 0;
00388     }
00389     
00390     T* get () const
00391     {
00392         return m_ptr;
00393     }
00394 
00395     bool is_managed () const
00396     {
00397         return m_managed;
00398     }
00399     
00400     void manage ()
00401     {
00402         m_managed = true;
00403     }
00404     
00405     void unmanage ()
00406     {
00407         m_managed = false;
00408     }
00409     
00410     void clean ()
00411     {
00412         if (m_managed) {
00413             delete m_ptr;
00414             m_ptr = 0;
00415         }
00416     }
00417 };
00418 
00419 template <class T>
00420 manage_me_ptr<T> manage (T* ptr)
00421 {
00422     return manage_me_ptr<T> (ptr);
00423 }
00424 
00425 template <class T>
00426 class mgr_container : public T
00427 {
00428 public:
00429     ~mgr_container ()
00430     {
00431         std::for_each (T::begin (),
00432                        T::end (),
00433                        std::mem_fun (&T::value_type::clean ()));
00434     }
00435 };
00436 
00437 template <class T>
00438 class mgr_assoc : public T
00439 {
00440 public:
00441     ~mgr_assoc ()
00442     {
00443         for (typename T::iterator it = T::begin ();
00444              it != T::end ();
00445              ++it)
00446             it->second.clean ();
00447     }
00448 };
00449 
00450 } /* namespace base */
00451 } /* namespace psynth*/
00452 
00453 namespace std
00454 {
00455 
00456 template <typename T>
00457 struct remove_pointer<psynth::base::null_ptr<T>>
00458 {
00459     typedef T type;
00460 };
00461 
00462 } /* namespace std */
00463 
00464 #endif /* PSYNTH_POINTER_HPP */