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