1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #ifndef GDCMSMARTPOINTER_H
15 #define GDCMSMARTPOINTER_H
16 
17 #include "gdcmObject.h"
18 
19 namespace gdcm
20 {
21 /**
22  * \brief Class for Smart Pointer
23  * \details
24  * Will only work for subclass of gdcm::Object
25  * See tr1/shared_ptr for a more general approach (not invasive)
26  * #include <tr1/memory>
27  * {
28  *   shared_ptr<Bla> b(new Bla);
29  * }
30  * \note
31  * Class partly based on post by Bill Hubauer:
32  * http://groups.google.com/group/comp.lang.c++/msg/173ddc38a827a930
33  * \see
34  * http://www.davethehat.com/articles/smartp.htm
35  *
36  * and itk::SmartPointer
37  */
38 template<class ObjectType>
39 class SmartPointer
40 {
41 public:
SmartPointer()42   SmartPointer():Pointer(nullptr) {}
SmartPointer(const SmartPointer<ObjectType> & p)43   SmartPointer(const SmartPointer<ObjectType>& p):Pointer(p.Pointer)
44     { Register(); }
SmartPointer(ObjectType * p)45   SmartPointer(ObjectType* p):Pointer(p)
46     { Register(); }
SmartPointer(ObjectType const & p)47   SmartPointer(ObjectType const & p)
48     {
49     Pointer = const_cast<ObjectType*>(&p);
50     Register();
51     }
~SmartPointer()52   ~SmartPointer() {
53     UnRegister();
54     Pointer = nullptr;
55   }
56 
57   /// Overload operator ->
58   ObjectType *operator -> () const
59     { return Pointer; }
60 
61   ObjectType& operator * () const
62     {
63     assert( Pointer );
64     return *Pointer;
65     }
66 
67   /// Return pointer to object.
68   operator ObjectType * () const
69     { return Pointer; }
70 
71   /// Overload operator assignment.
72   SmartPointer &operator = (SmartPointer const &r)
73     { return operator = (r.Pointer); }
74 
75   /// Overload operator assignment.
76   SmartPointer &operator = (ObjectType *r)
77     {
78     // http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.22
79     // DO NOT CHANGE THE ORDER OF THESE STATEMENTS!
80     // (This order properly handles self-assignment)
81     // (This order also properly handles recursion, e.g., if a ObjectType contains SmartPointer<ObjectType>s)
82     if( Pointer != r )
83       {
84       ObjectType* old = Pointer;
85       Pointer = r;
86       Register();
87       if ( old ) { old->UnRegister(); }
88       }
89     return *this;
90     }
91 
92   SmartPointer &operator = (ObjectType const &r)
93     {
94     ObjectType* tmp = const_cast<ObjectType*>(&r);
95     return operator = (tmp);
96     }
97 
98   /// Explicit function to retrieve the pointer
GetPointer()99   ObjectType *GetPointer() const
100     { return Pointer; }
101 
102 private:
Register()103   void Register()
104     {
105     if(Pointer) Pointer->Register();
106     }
107 
UnRegister()108   void UnRegister()
109     {
110     if(Pointer) Pointer->UnRegister();
111     }
112 
113   ObjectType* Pointer;
114 };
115 
116 } // end namespace gdcm
117 
118 #endif //GDCMSMARTPOINTER_H
119