nsAutoPtr.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsAutoPtr_h
  6. #define nsAutoPtr_h
  7. #include "nsCOMPtr.h"
  8. #include "mozilla/RefPtr.h"
  9. #include "mozilla/TypeTraits.h"
  10. #include "nsCycleCollectionNoteChild.h"
  11. #include "mozilla/MemoryReporting.h"
  12. /*****************************************************************************/
  13. // template <class T> class nsAutoPtrGetterTransfers;
  14. template <class T>
  15. class nsAutoPtr
  16. {
  17. private:
  18. static_assert(!mozilla::IsScalar<T>::value, "If you are using "
  19. "nsAutoPtr to hold an array, use UniquePtr<T[]> instead");
  20. void**
  21. begin_assignment()
  22. {
  23. assign(0);
  24. return reinterpret_cast<void**>(&mRawPtr);
  25. }
  26. void
  27. assign(T* aNewPtr)
  28. {
  29. T* oldPtr = mRawPtr;
  30. if (aNewPtr && aNewPtr == oldPtr) {
  31. NS_RUNTIMEABORT("Logic flaw in the caller");
  32. }
  33. mRawPtr = aNewPtr;
  34. delete oldPtr;
  35. }
  36. // |class Ptr| helps us prevent implicit "copy construction"
  37. // through |operator T*() const| from a |const nsAutoPtr<T>|
  38. // because two implicit conversions in a row aren't allowed.
  39. // It still allows assignment from T* through implicit conversion
  40. // from |T*| to |nsAutoPtr<T>::Ptr|
  41. class Ptr
  42. {
  43. public:
  44. MOZ_IMPLICIT Ptr(T* aPtr)
  45. : mPtr(aPtr)
  46. {
  47. }
  48. operator T*() const
  49. {
  50. return mPtr;
  51. }
  52. private:
  53. T* MOZ_NON_OWNING_REF mPtr;
  54. };
  55. private:
  56. T* MOZ_OWNING_REF mRawPtr;
  57. public:
  58. typedef T element_type;
  59. ~nsAutoPtr()
  60. {
  61. delete mRawPtr;
  62. }
  63. // Constructors
  64. nsAutoPtr()
  65. : mRawPtr(0)
  66. // default constructor
  67. {
  68. }
  69. MOZ_IMPLICIT nsAutoPtr(Ptr aRawPtr)
  70. : mRawPtr(aRawPtr)
  71. // construct from a raw pointer (of the right type)
  72. {
  73. }
  74. // This constructor shouldn't exist; we should just use the &&
  75. // constructor.
  76. nsAutoPtr(nsAutoPtr<T>& aSmartPtr)
  77. : mRawPtr(aSmartPtr.forget())
  78. // Construct by transferring ownership from another smart pointer.
  79. {
  80. }
  81. template <typename I>
  82. MOZ_IMPLICIT nsAutoPtr(nsAutoPtr<I>& aSmartPtr)
  83. : mRawPtr(aSmartPtr.forget())
  84. // Construct by transferring ownership from another smart pointer.
  85. {
  86. }
  87. nsAutoPtr(nsAutoPtr<T>&& aSmartPtr)
  88. : mRawPtr(aSmartPtr.forget())
  89. // Construct by transferring ownership from another smart pointer.
  90. {
  91. }
  92. template <typename I>
  93. MOZ_IMPLICIT nsAutoPtr(nsAutoPtr<I>&& aSmartPtr)
  94. : mRawPtr(aSmartPtr.forget())
  95. // Construct by transferring ownership from another smart pointer.
  96. {
  97. }
  98. // Assignment operators
  99. nsAutoPtr<T>&
  100. operator=(T* aRhs)
  101. // assign from a raw pointer (of the right type)
  102. {
  103. assign(aRhs);
  104. return *this;
  105. }
  106. nsAutoPtr<T>& operator=(nsAutoPtr<T>& aRhs)
  107. // assign by transferring ownership from another smart pointer.
  108. {
  109. assign(aRhs.forget());
  110. return *this;
  111. }
  112. template <typename I>
  113. nsAutoPtr<T>& operator=(nsAutoPtr<I>& aRhs)
  114. // assign by transferring ownership from another smart pointer.
  115. {
  116. assign(aRhs.forget());
  117. return *this;
  118. }
  119. nsAutoPtr<T>& operator=(nsAutoPtr<T>&& aRhs)
  120. {
  121. assign(aRhs.forget());
  122. return *this;
  123. }
  124. template <typename I>
  125. nsAutoPtr<T>& operator=(nsAutoPtr<I>&& aRhs)
  126. {
  127. assign(aRhs.forget());
  128. return *this;
  129. }
  130. // Other pointer operators
  131. T*
  132. get() const
  133. /*
  134. Prefer the implicit conversion provided automatically by
  135. |operator T*() const|. Use |get()| _only_ to resolve
  136. ambiguity.
  137. */
  138. {
  139. return mRawPtr;
  140. }
  141. operator T*() const
  142. /*
  143. ...makes an |nsAutoPtr| act like its underlying raw pointer
  144. type whenever it is used in a context where a raw pointer
  145. is expected. It is this operator that makes an |nsAutoPtr|
  146. substitutable for a raw pointer.
  147. Prefer the implicit use of this operator to calling |get()|,
  148. except where necessary to resolve ambiguity.
  149. */
  150. {
  151. return get();
  152. }
  153. T*
  154. forget()
  155. {
  156. T* temp = mRawPtr;
  157. mRawPtr = 0;
  158. return temp;
  159. }
  160. T*
  161. operator->() const
  162. {
  163. NS_PRECONDITION(mRawPtr != 0,
  164. "You can't dereference a NULL nsAutoPtr with operator->().");
  165. return get();
  166. }
  167. template <typename R, typename... Args>
  168. class Proxy
  169. {
  170. typedef R (T::*member_function)(Args...);
  171. T* mRawPtr;
  172. member_function mFunction;
  173. public:
  174. Proxy(T* aRawPtr, member_function aFunction)
  175. : mRawPtr(aRawPtr),
  176. mFunction(aFunction)
  177. {
  178. }
  179. template<typename... ActualArgs>
  180. R operator()(ActualArgs&&... aArgs)
  181. {
  182. return ((*mRawPtr).*mFunction)(mozilla::Forward<ActualArgs>(aArgs)...);
  183. }
  184. };
  185. template <typename R, typename C, typename... Args>
  186. Proxy<R, Args...> operator->*(R (C::*aFptr)(Args...)) const
  187. {
  188. NS_PRECONDITION(mRawPtr != 0,
  189. "You can't dereference a NULL nsAutoPtr with operator->*().");
  190. return Proxy<R, Args...>(get(), aFptr);
  191. }
  192. nsAutoPtr<T>*
  193. get_address()
  194. // This is not intended to be used by clients. See |address_of|
  195. // below.
  196. {
  197. return this;
  198. }
  199. const nsAutoPtr<T>*
  200. get_address() const
  201. // This is not intended to be used by clients. See |address_of|
  202. // below.
  203. {
  204. return this;
  205. }
  206. public:
  207. T&
  208. operator*() const
  209. {
  210. NS_PRECONDITION(mRawPtr != 0,
  211. "You can't dereference a NULL nsAutoPtr with operator*().");
  212. return *get();
  213. }
  214. T**
  215. StartAssignment()
  216. {
  217. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  218. return reinterpret_cast<T**>(begin_assignment());
  219. #else
  220. assign(0);
  221. return reinterpret_cast<T**>(&mRawPtr);
  222. #endif
  223. }
  224. };
  225. template <class T>
  226. inline nsAutoPtr<T>*
  227. address_of(nsAutoPtr<T>& aPtr)
  228. {
  229. return aPtr.get_address();
  230. }
  231. template <class T>
  232. inline const nsAutoPtr<T>*
  233. address_of(const nsAutoPtr<T>& aPtr)
  234. {
  235. return aPtr.get_address();
  236. }
  237. template <class T>
  238. class nsAutoPtrGetterTransfers
  239. /*
  240. ...
  241. This class is designed to be used for anonymous temporary objects in the
  242. argument list of calls that return COM interface pointers, e.g.,
  243. nsAutoPtr<IFoo> fooP;
  244. ...->GetTransferedPointer(getter_Transfers(fooP))
  245. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
  246. When initialized with a |nsAutoPtr|, as in the example above, it returns
  247. a |void**|, a |T**|, or an |nsISupports**| as needed, that the
  248. outer call (|GetTransferedPointer| in this case) can fill in.
  249. This type should be a nested class inside |nsAutoPtr<T>|.
  250. */
  251. {
  252. public:
  253. explicit
  254. nsAutoPtrGetterTransfers(nsAutoPtr<T>& aSmartPtr)
  255. : mTargetSmartPtr(aSmartPtr)
  256. {
  257. // nothing else to do
  258. }
  259. operator void**()
  260. {
  261. return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
  262. }
  263. operator T**()
  264. {
  265. return mTargetSmartPtr.StartAssignment();
  266. }
  267. T*&
  268. operator*()
  269. {
  270. return *(mTargetSmartPtr.StartAssignment());
  271. }
  272. private:
  273. nsAutoPtr<T>& mTargetSmartPtr;
  274. };
  275. template <class T>
  276. inline nsAutoPtrGetterTransfers<T>
  277. getter_Transfers(nsAutoPtr<T>& aSmartPtr)
  278. /*
  279. Used around a |nsAutoPtr| when
  280. ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
  281. */
  282. {
  283. return nsAutoPtrGetterTransfers<T>(aSmartPtr);
  284. }
  285. // Comparing two |nsAutoPtr|s
  286. template <class T, class U>
  287. inline bool
  288. operator==(const nsAutoPtr<T>& aLhs, const nsAutoPtr<U>& aRhs)
  289. {
  290. return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
  291. }
  292. template <class T, class U>
  293. inline bool
  294. operator!=(const nsAutoPtr<T>& aLhs, const nsAutoPtr<U>& aRhs)
  295. {
  296. return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
  297. }
  298. // Comparing an |nsAutoPtr| to a raw pointer
  299. template <class T, class U>
  300. inline bool
  301. operator==(const nsAutoPtr<T>& aLhs, const U* aRhs)
  302. {
  303. return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
  304. }
  305. template <class T, class U>
  306. inline bool
  307. operator==(const U* aLhs, const nsAutoPtr<T>& aRhs)
  308. {
  309. return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
  310. }
  311. template <class T, class U>
  312. inline bool
  313. operator!=(const nsAutoPtr<T>& aLhs, const U* aRhs)
  314. {
  315. return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
  316. }
  317. template <class T, class U>
  318. inline bool
  319. operator!=(const U* aLhs, const nsAutoPtr<T>& aRhs)
  320. {
  321. return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
  322. }
  323. template <class T, class U>
  324. inline bool
  325. operator==(const nsAutoPtr<T>& aLhs, U* aRhs)
  326. {
  327. return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
  328. }
  329. template <class T, class U>
  330. inline bool
  331. operator==(U* aLhs, const nsAutoPtr<T>& aRhs)
  332. {
  333. return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
  334. }
  335. template <class T, class U>
  336. inline bool
  337. operator!=(const nsAutoPtr<T>& aLhs, U* aRhs)
  338. {
  339. return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
  340. }
  341. template <class T, class U>
  342. inline bool
  343. operator!=(U* aLhs, const nsAutoPtr<T>& aRhs)
  344. {
  345. return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
  346. }
  347. // Comparing an |nsAutoPtr| to |nullptr|
  348. template <class T>
  349. inline bool
  350. operator==(const nsAutoPtr<T>& aLhs, decltype(nullptr))
  351. {
  352. return aLhs.get() == nullptr;
  353. }
  354. template <class T>
  355. inline bool
  356. operator==(decltype(nullptr), const nsAutoPtr<T>& aRhs)
  357. {
  358. return nullptr == aRhs.get();
  359. }
  360. template <class T>
  361. inline bool
  362. operator!=(const nsAutoPtr<T>& aLhs, decltype(nullptr))
  363. {
  364. return aLhs.get() != nullptr;
  365. }
  366. template <class T>
  367. inline bool
  368. operator!=(decltype(nullptr), const nsAutoPtr<T>& aRhs)
  369. {
  370. return nullptr != aRhs.get();
  371. }
  372. /*****************************************************************************/
  373. #endif // !defined(nsAutoPtr_h)