AutoPtr.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. //
  2. // AutoPtr.h
  3. //
  4. // Library: Foundation
  5. // Package: Core
  6. // Module: AutoPtr
  7. //
  8. // Definition of the AutoPtr template class.
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_AutoPtr_INCLUDED
  16. #define Foundation_AutoPtr_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #include "Poco/Exception.h"
  19. #include <algorithm>
  20. namespace Poco {
  21. template <class C>
  22. class AutoPtr
  23. /// AutoPtr is a "smart" pointer for classes implementing
  24. /// reference counting based garbage collection.
  25. /// To be usable with the AutoPtr template, a class must
  26. /// implement the following behaviour:
  27. /// A class must maintain a reference count.
  28. /// The constructors of the object initialize the reference
  29. /// count to one.
  30. /// The class must implement a public duplicate() method:
  31. /// void duplicate();
  32. /// that increments the reference count by one.
  33. /// The class must implement a public release() method:
  34. /// void release()
  35. /// that decrements the reference count by one, and,
  36. /// if the reference count reaches zero, deletes the
  37. /// object.
  38. ///
  39. /// AutoPtr works in the following way:
  40. /// If an AutoPtr is assigned an ordinary pointer to
  41. /// an object (via the constructor or the assignment operator),
  42. /// it takes ownership of the object and the object's reference
  43. /// count remains unchanged.
  44. /// If the AutoPtr is assigned another AutoPtr, the
  45. /// object's reference count is incremented by one by
  46. /// calling duplicate() on its object.
  47. /// The destructor of AutoPtr calls release() on its
  48. /// object.
  49. /// AutoPtr supports dereferencing with both the ->
  50. /// and the * operator. An attempt to dereference a null
  51. /// AutoPtr results in a NullPointerException being thrown.
  52. /// AutoPtr also implements all relational operators.
  53. /// Note that AutoPtr allows casting of its encapsulated data types.
  54. {
  55. public:
  56. AutoPtr(): _ptr(0)
  57. {
  58. }
  59. AutoPtr(C* ptr): _ptr(ptr)
  60. {
  61. }
  62. AutoPtr(C* ptr, bool shared): _ptr(ptr)
  63. {
  64. if (shared && _ptr) _ptr->duplicate();
  65. }
  66. AutoPtr(const AutoPtr& ptr): _ptr(ptr._ptr)
  67. {
  68. if (_ptr) _ptr->duplicate();
  69. }
  70. template <class Other>
  71. AutoPtr(const AutoPtr<Other>& ptr): _ptr(const_cast<Other*>(ptr.get()))
  72. {
  73. if (_ptr) _ptr->duplicate();
  74. }
  75. ~AutoPtr()
  76. {
  77. if (_ptr) _ptr->release();
  78. }
  79. AutoPtr& assign(C* ptr)
  80. {
  81. if (_ptr != ptr)
  82. {
  83. if (_ptr) _ptr->release();
  84. _ptr = ptr;
  85. }
  86. return *this;
  87. }
  88. AutoPtr& assign(C* ptr, bool shared)
  89. {
  90. if (_ptr != ptr)
  91. {
  92. if (_ptr) _ptr->release();
  93. _ptr = ptr;
  94. if (shared && _ptr) _ptr->duplicate();
  95. }
  96. return *this;
  97. }
  98. AutoPtr& assign(const AutoPtr& ptr)
  99. {
  100. if (&ptr != this)
  101. {
  102. if (_ptr) _ptr->release();
  103. _ptr = ptr._ptr;
  104. if (_ptr) _ptr->duplicate();
  105. }
  106. return *this;
  107. }
  108. template <class Other>
  109. AutoPtr& assign(const AutoPtr<Other>& ptr)
  110. {
  111. if (ptr.get() != _ptr)
  112. {
  113. if (_ptr) _ptr->release();
  114. _ptr = const_cast<Other*>(ptr.get());
  115. if (_ptr) _ptr->duplicate();
  116. }
  117. return *this;
  118. }
  119. void reset()
  120. {
  121. if (_ptr)
  122. {
  123. _ptr->release();
  124. _ptr = 0;
  125. }
  126. }
  127. void reset(C* ptr)
  128. {
  129. assign(ptr);
  130. }
  131. void reset(C* ptr, bool shared)
  132. {
  133. assign(ptr, shared);
  134. }
  135. void reset(const AutoPtr& ptr)
  136. {
  137. assign(ptr);
  138. }
  139. template <class Other>
  140. void reset(const AutoPtr<Other>& ptr)
  141. {
  142. assign<Other>(ptr);
  143. }
  144. AutoPtr& operator = (C* ptr)
  145. {
  146. return assign(ptr);
  147. }
  148. AutoPtr& operator = (const AutoPtr& ptr)
  149. {
  150. return assign(ptr);
  151. }
  152. template <class Other>
  153. AutoPtr& operator = (const AutoPtr<Other>& ptr)
  154. {
  155. return assign<Other>(ptr);
  156. }
  157. void swap(AutoPtr& ptr)
  158. {
  159. std::swap(_ptr, ptr._ptr);
  160. }
  161. template <class Other>
  162. AutoPtr<Other> cast() const
  163. /// Casts the AutoPtr via a dynamic cast to the given type.
  164. /// Returns an AutoPtr containing NULL if the cast fails.
  165. /// Example: (assume class Sub: public Super)
  166. /// AutoPtr<Super> super(new Sub());
  167. /// AutoPtr<Sub> sub = super.cast<Sub>();
  168. /// poco_assert (sub.get());
  169. {
  170. Other* pOther = dynamic_cast<Other*>(_ptr);
  171. return AutoPtr<Other>(pOther, true);
  172. }
  173. template <class Other>
  174. AutoPtr<Other> unsafeCast() const
  175. /// Casts the AutoPtr via a static cast to the given type.
  176. /// Example: (assume class Sub: public Super)
  177. /// AutoPtr<Super> super(new Sub());
  178. /// AutoPtr<Sub> sub = super.unsafeCast<Sub>();
  179. /// poco_assert (sub.get());
  180. {
  181. Other* pOther = static_cast<Other*>(_ptr);
  182. return AutoPtr<Other>(pOther, true);
  183. }
  184. C* operator -> ()
  185. {
  186. if (_ptr)
  187. return _ptr;
  188. else
  189. throw NullPointerException();
  190. }
  191. const C* operator -> () const
  192. {
  193. if (_ptr)
  194. return _ptr;
  195. else
  196. throw NullPointerException();
  197. }
  198. C& operator * ()
  199. {
  200. if (_ptr)
  201. return *_ptr;
  202. else
  203. throw NullPointerException();
  204. }
  205. const C& operator * () const
  206. {
  207. if (_ptr)
  208. return *_ptr;
  209. else
  210. throw NullPointerException();
  211. }
  212. C* get()
  213. {
  214. return _ptr;
  215. }
  216. const C* get() const
  217. {
  218. return _ptr;
  219. }
  220. operator C* ()
  221. {
  222. return _ptr;
  223. }
  224. operator const C* () const
  225. {
  226. return _ptr;
  227. }
  228. bool operator ! () const
  229. {
  230. return _ptr == 0;
  231. }
  232. bool isNull() const
  233. {
  234. return _ptr == 0;
  235. }
  236. C* duplicate()
  237. {
  238. if (_ptr) _ptr->duplicate();
  239. return _ptr;
  240. }
  241. bool operator == (const AutoPtr& ptr) const
  242. {
  243. return _ptr == ptr._ptr;
  244. }
  245. bool operator == (const C* ptr) const
  246. {
  247. return _ptr == ptr;
  248. }
  249. bool operator == (C* ptr) const
  250. {
  251. return _ptr == ptr;
  252. }
  253. bool operator != (const AutoPtr& ptr) const
  254. {
  255. return _ptr != ptr._ptr;
  256. }
  257. bool operator != (const C* ptr) const
  258. {
  259. return _ptr != ptr;
  260. }
  261. bool operator != (C* ptr) const
  262. {
  263. return _ptr != ptr;
  264. }
  265. bool operator < (const AutoPtr& ptr) const
  266. {
  267. return _ptr < ptr._ptr;
  268. }
  269. bool operator < (const C* ptr) const
  270. {
  271. return _ptr < ptr;
  272. }
  273. bool operator < (C* ptr) const
  274. {
  275. return _ptr < ptr;
  276. }
  277. bool operator <= (const AutoPtr& ptr) const
  278. {
  279. return _ptr <= ptr._ptr;
  280. }
  281. bool operator <= (const C* ptr) const
  282. {
  283. return _ptr <= ptr;
  284. }
  285. bool operator <= (C* ptr) const
  286. {
  287. return _ptr <= ptr;
  288. }
  289. bool operator > (const AutoPtr& ptr) const
  290. {
  291. return _ptr > ptr._ptr;
  292. }
  293. bool operator > (const C* ptr) const
  294. {
  295. return _ptr > ptr;
  296. }
  297. bool operator > (C* ptr) const
  298. {
  299. return _ptr > ptr;
  300. }
  301. bool operator >= (const AutoPtr& ptr) const
  302. {
  303. return _ptr >= ptr._ptr;
  304. }
  305. bool operator >= (const C* ptr) const
  306. {
  307. return _ptr >= ptr;
  308. }
  309. bool operator >= (C* ptr) const
  310. {
  311. return _ptr >= ptr;
  312. }
  313. private:
  314. C* _ptr;
  315. };
  316. template <class C>
  317. inline void swap(AutoPtr<C>& p1, AutoPtr<C>& p2)
  318. {
  319. p1.swap(p2);
  320. }
  321. } // namespace Poco
  322. #endif // Foundation_AutoPtr_INCLUDED