1 // This file may be redistributed and modified only under the terms of
2 // the GNU Lesser General Public License (See COPYING for details).
3 // Copyright (C) 2000 Aloril
4 // Copyright (C) 2000-2005 Al Riddoch
5 
6 // $Id$
7 
8 #ifndef ATLAS_OBJECTS_SMARTPTR_H
9 #define ATLAS_OBJECTS_SMARTPTR_H
10 
11 #include <Atlas/Exception.h>
12 
13 namespace Atlas { namespace Objects {
14 
15 class NullSmartPtrDereference : public Atlas::Exception
16 {
17   public:
NullSmartPtrDereference()18     NullSmartPtrDereference() : Atlas::Exception("Null SmartPtr dereferenced") {}
19     virtual ~NullSmartPtrDereference();
20 };
21 
22 template <class T>
23 class SmartPtr
24 {
25   public:
26     typedef T DataT;
27 
28     typedef typename T::iterator iterator;
29     typedef typename T::const_iterator const_iterator;
30 
SmartPtr()31     SmartPtr() : ptr(T::alloc()) {
32     }
SmartPtr(const SmartPtr<T> & a)33     SmartPtr(const SmartPtr<T>& a) : ptr(a.get()) {
34         incRef();
35     }
SmartPtr(T * a_ptr)36     SmartPtr(T *a_ptr) : ptr(a_ptr)
37     {
38         incRef();
39     }
40     template<class oldType>
SmartPtr(const SmartPtr<oldType> & a)41     explicit SmartPtr(const SmartPtr<oldType>& a) : ptr(a.get()) {
42     }
~SmartPtr()43     ~SmartPtr() {
44         decRef();
45     }
46     SmartPtr& operator=(const SmartPtr<T>& a) {
47         if (a.get() != this->get()) {
48             decRef();
49             ptr = a.get();
50             incRef();
51         }
52         return *this;
53     }
54     template<class newType>
55     operator SmartPtr<newType>() const {
56         return SmartPtr<newType>(ptr);
57     }
58     template<class newType>
59     operator SmartPtr<const newType>() const {
60         return SmartPtr<const newType>(ptr);
61     }
isValid()62     bool isValid() const {
63         return ptr != 0;
64     }
65     T& operator*() const {
66         if (ptr == 0) {
67             throw NullSmartPtrDereference();
68         }
69         return *ptr;
70     }
71     T* operator->() const {
72         if (ptr == 0) {
73             throw NullSmartPtrDereference();
74         }
75         return ptr;
76     }
get()77     T* get() const {
78         return ptr;
79     }
copy()80     SmartPtr<T> copy() const
81     {
82         SmartPtr<T> ret = SmartPtr(ptr->copy());
83         ret.decRef();
84         return ret;
85     }
getDefaultObject()86     SmartPtr<T> getDefaultObject() const
87     {
88         return SmartPtr(ptr->getDefaultObject());
89     }
90     // If you want to make these protected, please ensure that the
91     // detructor is made virtual to ensure your new class bahaves
92     // correctly.
93   private:
decRef()94     void decRef() const {
95         if (ptr != 0) {
96             ptr->decRef();
97         }
98     }
incRef()99     void incRef() const {
100         if (ptr != 0) {
101             ptr->incRef();
102         }
103     }
104     T * ptr;
105 };
106 
107 template<typename returnPtrType, class fromType>
smart_dynamic_cast(const SmartPtr<fromType> & o)108 returnPtrType smart_dynamic_cast(const SmartPtr<fromType> & o)
109 {
110     return returnPtrType(dynamic_cast<typename returnPtrType::DataT*>(o.get()));
111 }
112 
113 template<typename returnPtrType, class fromType>
smart_static_cast(const SmartPtr<fromType> & o)114 returnPtrType smart_static_cast(const SmartPtr<fromType> & o)
115 {
116     return returnPtrType((typename returnPtrType::DataT *)o.get());
117 }
118 
119 } } // namespace Atlas::Objects
120 
121 #endif // ATLAS_OBJECTS_SMARTPTR_H
122