Atlas  0.7.0
Networking protocol for the Worldforge system.
SmartPtr.h
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 #include <cassert>
13 
14 namespace Atlas { namespace Objects {
15 
16 template <class T>
17 class SmartPtr
18 {
19  public:
20  template<class U> friend
21  class SmartPtr;
22 
23  typedef T DataT;
24 
25  SmartPtr() noexcept : ptr(T::allocator.alloc()) {
26  }
27  SmartPtr(const SmartPtr<T>& a) noexcept : ptr(a.get()) {
28  incRef();
29  }
30  SmartPtr(SmartPtr<T>&& a) noexcept : ptr(a.get()) {
31  a.ptr = nullptr;
32  }
33  SmartPtr(T *a_ptr) noexcept : ptr(a_ptr)
34  {
35  incRef();
36  }
37  template<class oldType>
38  explicit SmartPtr(const SmartPtr<oldType>& a) noexcept : ptr(a.get()) {
39  incRef();
40  }
41  template<class oldType>
42  explicit SmartPtr(SmartPtr<oldType>&& a) noexcept : ptr(a.get()) {
43  a.ptr = nullptr;
44  }
45  ~SmartPtr() {
46  decRef();
47  }
48  SmartPtr& operator=(const SmartPtr<T>& a) noexcept {
49  if (a.get() != this->get()) {
50  decRef();
51  ptr = a.get();
52  incRef();
53  }
54  return *this;
55  }
56 
57  SmartPtr& operator=(SmartPtr<T>&& a) noexcept {
58  if (a.get() != this->get()) {
59  //Do a dec-ref on the existing ptr (if any)
60  decRef();
61  //But don't do any increase on the new one, just move it over.
62  // The reference number on it will stay the same, which is what we want.
63  ptr = a.get();
64  a.ptr = nullptr;
65  }
66  return *this;
67  }
68 
69  template<class newType>
70  operator SmartPtr<newType>() const noexcept {
71  return SmartPtr<newType>(ptr);
72  }
73  template<class newType>
74  operator SmartPtr<const newType>() const noexcept {
75  return SmartPtr<const newType>(ptr);
76  }
77  constexpr bool isValid() const noexcept {
78  return ptr != nullptr;
79  }
80  constexpr bool operator!() const noexcept {
81  return this->ptr == nullptr;
82  }
83 
84  explicit constexpr operator bool () const noexcept
85  {
86  return !this->operator!();
87  }
88 
89  constexpr T& operator*() const noexcept {
90  assert(ptr);
91  return *ptr;
92  }
93  constexpr T* operator->() const noexcept {
94  assert(ptr);
95  return ptr;
96  }
97  constexpr T* get() const noexcept {
98  return ptr;
99  }
100  SmartPtr<T> copy() const noexcept
101  {
102  return SmartPtr(ptr->copy());
103  }
104  // If you want to make these protected, please ensure that the
105  // destructor is made virtual to ensure your new class behaves
106  // correctly.
107  private:
108  void decRef() const noexcept {
109  if (ptr != nullptr) {
110  ptr->decRef();
111  }
112  }
113  void incRef() const noexcept {
114  if (ptr != nullptr) {
115  ptr->incRef();
116  }
117  }
118  T * ptr;
119 };
120 
121 template<typename returnPtrType, class fromType>
122 returnPtrType smart_dynamic_cast(const SmartPtr<fromType> & o)
123 {
124  return returnPtrType(dynamic_cast<typename returnPtrType::DataT*>(o.get()));
125 }
126 
127 template<typename returnPtrType, class fromType>
128 returnPtrType smart_static_cast(const SmartPtr<fromType> & o)
129 {
130  return returnPtrType((typename returnPtrType::DataT *)o.get());
131 }
132 
133 } } // namespace Atlas::Objects
134 
135 #endif // ATLAS_OBJECTS_SMARTPTR_H
Definition: Bridge.h:20