Bug 439354 - OS X toolbar background doesn't have a good gradient, part 1 / 3, r...
[mozilla-central.git] / xpcom / base / nsAutoPtr.h
blobb622ef8701b59af15a424f356ec37955873d429f
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Scott Collins <scc@mozilla.org> (original author of nsCOMPtr)
24 * L. David Baron <dbaron@dbaron.org>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef nsAutoPtr_h___
41 #define nsAutoPtr_h___
43 // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
44 #ifndef nsCOMPtr_h___
45 // For |already_AddRefed|, |NSCAP_Zero|,
46 // |NSCAP_DONT_PROVIDE_NONCONST_OPEQ|,
47 // |NSCAP_FEATURE_INLINE_STARTASSIGNMENT|
48 #include "nsCOMPtr.h"
49 #endif
51 /*****************************************************************************/
53 // template <class T> class nsAutoPtrGetterTransfers;
55 template <class T>
56 class nsAutoPtr
58 private:
59 void**
60 begin_assignment()
62 assign(0);
63 return reinterpret_cast<void**>(&mRawPtr);
66 void
67 assign( T* newPtr )
69 T* oldPtr = mRawPtr;
70 mRawPtr = newPtr;
71 delete oldPtr;
74 // |class Ptr| helps us prevent implicit "copy construction"
75 // through |operator T*() const| from a |const nsAutoPtr<T>|
76 // because two implicit conversions in a row aren't allowed.
77 // It still allows assignment from T* through implicit conversion
78 // from |T*| to |nsAutoPtr<T>::Ptr|
79 class Ptr
81 public:
82 Ptr( T* aPtr )
83 : mPtr(aPtr)
87 operator T*() const
89 return mPtr;
92 private:
93 T* mPtr;
96 private:
97 T* mRawPtr;
99 public:
100 typedef T element_type;
102 ~nsAutoPtr()
104 delete mRawPtr;
107 // Constructors
109 nsAutoPtr()
110 : mRawPtr(0)
111 // default constructor
115 nsAutoPtr( Ptr aRawPtr )
116 : mRawPtr(aRawPtr)
117 // construct from a raw pointer (of the right type)
121 nsAutoPtr( nsAutoPtr<T>& aSmartPtr )
122 : mRawPtr( aSmartPtr.forget() )
123 // Construct by transferring ownership from another smart pointer.
128 // Assignment operators
130 nsAutoPtr<T>&
131 operator=( T* rhs )
132 // assign from a raw pointer (of the right type)
134 assign(rhs);
135 return *this;
138 nsAutoPtr<T>& operator=( nsAutoPtr<T>& rhs )
139 // assign by transferring ownership from another smart pointer.
141 assign(rhs.forget());
142 return *this;
145 // Other pointer operators
148 get() const
150 Prefer the implicit conversion provided automatically by
151 |operator T*() const|. Use |get()| _only_ to resolve
152 ambiguity.
155 return mRawPtr;
158 operator T*() const
160 ...makes an |nsAutoPtr| act like its underlying raw pointer
161 type whenever it is used in a context where a raw pointer
162 is expected. It is this operator that makes an |nsAutoPtr|
163 substitutable for a raw pointer.
165 Prefer the implicit use of this operator to calling |get()|,
166 except where necessary to resolve ambiguity.
169 return get();
173 forget()
175 T* temp = mRawPtr;
176 mRawPtr = 0;
177 return temp;
181 operator->() const
183 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->().");
184 return get();
187 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
188 // broken version for IRIX
190 nsAutoPtr<T>*
191 get_address() const
192 // This is not intended to be used by clients. See |address_of|
193 // below.
195 return const_cast<nsAutoPtr<T>*>(this);
198 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
200 nsAutoPtr<T>*
201 get_address()
202 // This is not intended to be used by clients. See |address_of|
203 // below.
205 return this;
208 const nsAutoPtr<T>*
209 get_address() const
210 // This is not intended to be used by clients. See |address_of|
211 // below.
213 return this;
216 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
218 public:
220 operator*() const
222 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*().");
223 return *get();
227 StartAssignment()
229 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
230 return reinterpret_cast<T**>(begin_assignment());
231 #else
232 assign(0);
233 return reinterpret_cast<T**>(&mRawPtr);
234 #endif
238 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
240 // This is the broken version for IRIX, which can't handle the version below.
242 template <class T>
243 inline
244 nsAutoPtr<T>*
245 address_of( const nsAutoPtr<T>& aPtr )
247 return aPtr.get_address();
250 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
252 template <class T>
253 inline
254 nsAutoPtr<T>*
255 address_of( nsAutoPtr<T>& aPtr )
257 return aPtr.get_address();
260 template <class T>
261 inline
262 const nsAutoPtr<T>*
263 address_of( const nsAutoPtr<T>& aPtr )
265 return aPtr.get_address();
268 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
270 template <class T>
271 class nsAutoPtrGetterTransfers
275 This class is designed to be used for anonymous temporary objects in the
276 argument list of calls that return COM interface pointers, e.g.,
278 nsAutoPtr<IFoo> fooP;
279 ...->GetTransferedPointer(getter_Transfers(fooP))
281 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
283 When initialized with a |nsAutoPtr|, as in the example above, it returns
284 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
285 outer call (|GetTransferedPointer| in this case) can fill in.
287 This type should be a nested class inside |nsAutoPtr<T>|.
290 public:
291 explicit
292 nsAutoPtrGetterTransfers( nsAutoPtr<T>& aSmartPtr )
293 : mTargetSmartPtr(aSmartPtr)
295 // nothing else to do
298 operator void**()
300 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
303 operator T**()
305 return mTargetSmartPtr.StartAssignment();
309 operator*()
311 return *(mTargetSmartPtr.StartAssignment());
314 private:
315 nsAutoPtr<T>& mTargetSmartPtr;
318 template <class T>
319 inline
320 nsAutoPtrGetterTransfers<T>
321 getter_Transfers( nsAutoPtr<T>& aSmartPtr )
323 Used around a |nsAutoPtr| when
324 ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
327 return nsAutoPtrGetterTransfers<T>(aSmartPtr);
332 // Comparing two |nsAutoPtr|s
334 template <class T, class U>
335 inline
336 NSCAP_BOOL
337 operator==( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
339 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
343 template <class T, class U>
344 inline
345 NSCAP_BOOL
346 operator!=( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
348 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
352 // Comparing an |nsAutoPtr| to a raw pointer
354 template <class T, class U>
355 inline
356 NSCAP_BOOL
357 operator==( const nsAutoPtr<T>& lhs, const U* rhs )
359 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
362 template <class T, class U>
363 inline
364 NSCAP_BOOL
365 operator==( const U* lhs, const nsAutoPtr<T>& rhs )
367 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
370 template <class T, class U>
371 inline
372 NSCAP_BOOL
373 operator!=( const nsAutoPtr<T>& lhs, const U* rhs )
375 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
378 template <class T, class U>
379 inline
380 NSCAP_BOOL
381 operator!=( const U* lhs, const nsAutoPtr<T>& rhs )
383 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
386 // To avoid ambiguities caused by the presence of builtin |operator==|s
387 // creating a situation where one of the |operator==| defined above
388 // has a better conversion for one argument and the builtin has a
389 // better conversion for the other argument, define additional
390 // |operator==| without the |const| on the raw pointer.
391 // See bug 65664 for details.
393 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
394 template <class T, class U>
395 inline
396 NSCAP_BOOL
397 operator==( const nsAutoPtr<T>& lhs, U* rhs )
399 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
402 template <class T, class U>
403 inline
404 NSCAP_BOOL
405 operator==( U* lhs, const nsAutoPtr<T>& rhs )
407 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
410 template <class T, class U>
411 inline
412 NSCAP_BOOL
413 operator!=( const nsAutoPtr<T>& lhs, U* rhs )
415 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
418 template <class T, class U>
419 inline
420 NSCAP_BOOL
421 operator!=( U* lhs, const nsAutoPtr<T>& rhs )
423 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
425 #endif
429 // Comparing an |nsAutoPtr| to |0|
431 template <class T>
432 inline
433 NSCAP_BOOL
434 operator==( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
435 // specifically to allow |smartPtr == 0|
437 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
440 template <class T>
441 inline
442 NSCAP_BOOL
443 operator==( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
444 // specifically to allow |0 == smartPtr|
446 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
449 template <class T>
450 inline
451 NSCAP_BOOL
452 operator!=( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
453 // specifically to allow |smartPtr != 0|
455 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
458 template <class T>
459 inline
460 NSCAP_BOOL
461 operator!=( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
462 // specifically to allow |0 != smartPtr|
464 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
468 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
470 // We need to explicitly define comparison operators for `int'
471 // because the compiler is lame.
473 template <class T>
474 inline
475 NSCAP_BOOL
476 operator==( const nsAutoPtr<T>& lhs, int rhs )
477 // specifically to allow |smartPtr == 0|
479 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
482 template <class T>
483 inline
484 NSCAP_BOOL
485 operator==( int lhs, const nsAutoPtr<T>& rhs )
486 // specifically to allow |0 == smartPtr|
488 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
491 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
493 /*****************************************************************************/
495 // template <class T> class nsAutoArrayPtrGetterTransfers;
497 template <class T>
498 class nsAutoArrayPtr
500 private:
501 void**
502 begin_assignment()
504 assign(0);
505 return reinterpret_cast<void**>(&mRawPtr);
508 void
509 assign( T* newPtr )
511 T* oldPtr = mRawPtr;
512 mRawPtr = newPtr;
513 delete [] oldPtr;
516 private:
517 T* mRawPtr;
519 public:
520 typedef T element_type;
522 ~nsAutoArrayPtr()
524 delete [] mRawPtr;
527 // Constructors
529 nsAutoArrayPtr()
530 : mRawPtr(0)
531 // default constructor
535 nsAutoArrayPtr( T* aRawPtr )
536 : mRawPtr(aRawPtr)
537 // construct from a raw pointer (of the right type)
541 nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr )
542 : mRawPtr( aSmartPtr.forget() )
543 // Construct by transferring ownership from another smart pointer.
548 // Assignment operators
550 nsAutoArrayPtr<T>&
551 operator=( T* rhs )
552 // assign from a raw pointer (of the right type)
554 assign(rhs);
555 return *this;
558 nsAutoArrayPtr<T>& operator=( nsAutoArrayPtr<T>& rhs )
559 // assign by transferring ownership from another smart pointer.
561 assign(rhs.forget());
562 return *this;
565 // Other pointer operators
568 get() const
570 Prefer the implicit conversion provided automatically by
571 |operator T*() const|. Use |get()| _only_ to resolve
572 ambiguity.
575 return mRawPtr;
578 operator T*() const
580 ...makes an |nsAutoArrayPtr| act like its underlying raw pointer
581 type whenever it is used in a context where a raw pointer
582 is expected. It is this operator that makes an |nsAutoArrayPtr|
583 substitutable for a raw pointer.
585 Prefer the implicit use of this operator to calling |get()|,
586 except where necessary to resolve ambiguity.
589 return get();
593 forget()
595 T* temp = mRawPtr;
596 mRawPtr = 0;
597 return temp;
601 operator->() const
603 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->().");
604 return get();
607 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
608 // broken version for IRIX
610 nsAutoArrayPtr<T>*
611 get_address() const
612 // This is not intended to be used by clients. See |address_of|
613 // below.
615 return const_cast<nsAutoArrayPtr<T>*>(this);
618 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
620 nsAutoArrayPtr<T>*
621 get_address()
622 // This is not intended to be used by clients. See |address_of|
623 // below.
625 return this;
628 const nsAutoArrayPtr<T>*
629 get_address() const
630 // This is not intended to be used by clients. See |address_of|
631 // below.
633 return this;
636 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
638 public:
640 operator*() const
642 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*().");
643 return *get();
647 StartAssignment()
649 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
650 return reinterpret_cast<T**>(begin_assignment());
651 #else
652 assign(0);
653 return reinterpret_cast<T**>(&mRawPtr);
654 #endif
658 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
660 // This is the broken version for IRIX, which can't handle the version below.
662 template <class T>
663 inline
664 nsAutoArrayPtr<T>*
665 address_of( const nsAutoArrayPtr<T>& aPtr )
667 return aPtr.get_address();
670 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
672 template <class T>
673 inline
674 nsAutoArrayPtr<T>*
675 address_of( nsAutoArrayPtr<T>& aPtr )
677 return aPtr.get_address();
680 template <class T>
681 inline
682 const nsAutoArrayPtr<T>*
683 address_of( const nsAutoArrayPtr<T>& aPtr )
685 return aPtr.get_address();
688 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
690 template <class T>
691 class nsAutoArrayPtrGetterTransfers
695 This class is designed to be used for anonymous temporary objects in the
696 argument list of calls that return COM interface pointers, e.g.,
698 nsAutoArrayPtr<IFoo> fooP;
699 ...->GetTransferedPointer(getter_Transfers(fooP))
701 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
703 When initialized with a |nsAutoArrayPtr|, as in the example above, it returns
704 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
705 outer call (|GetTransferedPointer| in this case) can fill in.
707 This type should be a nested class inside |nsAutoArrayPtr<T>|.
710 public:
711 explicit
712 nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr<T>& aSmartPtr )
713 : mTargetSmartPtr(aSmartPtr)
715 // nothing else to do
718 operator void**()
720 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
723 operator T**()
725 return mTargetSmartPtr.StartAssignment();
729 operator*()
731 return *(mTargetSmartPtr.StartAssignment());
734 private:
735 nsAutoArrayPtr<T>& mTargetSmartPtr;
738 template <class T>
739 inline
740 nsAutoArrayPtrGetterTransfers<T>
741 getter_Transfers( nsAutoArrayPtr<T>& aSmartPtr )
743 Used around a |nsAutoArrayPtr| when
744 ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible.
747 return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr);
752 // Comparing two |nsAutoArrayPtr|s
754 template <class T, class U>
755 inline
756 NSCAP_BOOL
757 operator==( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
759 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
763 template <class T, class U>
764 inline
765 NSCAP_BOOL
766 operator!=( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
768 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
772 // Comparing an |nsAutoArrayPtr| to a raw pointer
774 template <class T, class U>
775 inline
776 NSCAP_BOOL
777 operator==( const nsAutoArrayPtr<T>& lhs, const U* rhs )
779 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
782 template <class T, class U>
783 inline
784 NSCAP_BOOL
785 operator==( const U* lhs, const nsAutoArrayPtr<T>& rhs )
787 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
790 template <class T, class U>
791 inline
792 NSCAP_BOOL
793 operator!=( const nsAutoArrayPtr<T>& lhs, const U* rhs )
795 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
798 template <class T, class U>
799 inline
800 NSCAP_BOOL
801 operator!=( const U* lhs, const nsAutoArrayPtr<T>& rhs )
803 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
806 // To avoid ambiguities caused by the presence of builtin |operator==|s
807 // creating a situation where one of the |operator==| defined above
808 // has a better conversion for one argument and the builtin has a
809 // better conversion for the other argument, define additional
810 // |operator==| without the |const| on the raw pointer.
811 // See bug 65664 for details.
813 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
814 template <class T, class U>
815 inline
816 NSCAP_BOOL
817 operator==( const nsAutoArrayPtr<T>& lhs, U* rhs )
819 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
822 template <class T, class U>
823 inline
824 NSCAP_BOOL
825 operator==( U* lhs, const nsAutoArrayPtr<T>& rhs )
827 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
830 template <class T, class U>
831 inline
832 NSCAP_BOOL
833 operator!=( const nsAutoArrayPtr<T>& lhs, U* rhs )
835 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
838 template <class T, class U>
839 inline
840 NSCAP_BOOL
841 operator!=( U* lhs, const nsAutoArrayPtr<T>& rhs )
843 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
845 #endif
849 // Comparing an |nsAutoArrayPtr| to |0|
851 template <class T>
852 inline
853 NSCAP_BOOL
854 operator==( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
855 // specifically to allow |smartPtr == 0|
857 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
860 template <class T>
861 inline
862 NSCAP_BOOL
863 operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
864 // specifically to allow |0 == smartPtr|
866 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
869 template <class T>
870 inline
871 NSCAP_BOOL
872 operator!=( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
873 // specifically to allow |smartPtr != 0|
875 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
878 template <class T>
879 inline
880 NSCAP_BOOL
881 operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
882 // specifically to allow |0 != smartPtr|
884 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
888 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
890 // We need to explicitly define comparison operators for `int'
891 // because the compiler is lame.
893 template <class T>
894 inline
895 NSCAP_BOOL
896 operator==( const nsAutoArrayPtr<T>& lhs, int rhs )
897 // specifically to allow |smartPtr == 0|
899 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
902 template <class T>
903 inline
904 NSCAP_BOOL
905 operator==( int lhs, const nsAutoArrayPtr<T>& rhs )
906 // specifically to allow |0 == smartPtr|
908 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
911 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
914 /*****************************************************************************/
916 // template <class T> class nsRefPtrGetterAddRefs;
918 template <class T>
919 class nsRefPtr
921 private:
923 void
924 assign_with_AddRef( T* rawPtr )
926 if ( rawPtr )
927 rawPtr->AddRef();
928 assign_assuming_AddRef(rawPtr);
931 void**
932 begin_assignment()
934 assign_assuming_AddRef(0);
935 return reinterpret_cast<void**>(&mRawPtr);
938 void
939 assign_assuming_AddRef( T* newPtr )
941 T* oldPtr = mRawPtr;
942 mRawPtr = newPtr;
943 if ( oldPtr )
944 oldPtr->Release();
947 private:
948 T* mRawPtr;
950 public:
951 typedef T element_type;
953 ~nsRefPtr()
955 if ( mRawPtr )
956 mRawPtr->Release();
959 // Constructors
961 nsRefPtr()
962 : mRawPtr(0)
963 // default constructor
967 nsRefPtr( const nsRefPtr<T>& aSmartPtr )
968 : mRawPtr(aSmartPtr.mRawPtr)
969 // copy-constructor
971 if ( mRawPtr )
972 mRawPtr->AddRef();
975 nsRefPtr( T* aRawPtr )
976 : mRawPtr(aRawPtr)
977 // construct from a raw pointer (of the right type)
979 if ( mRawPtr )
980 mRawPtr->AddRef();
983 nsRefPtr( const already_AddRefed<T>& aSmartPtr )
984 : mRawPtr(aSmartPtr.mRawPtr)
985 // construct from |dont_AddRef(expr)|
989 // Assignment operators
991 nsRefPtr<T>&
992 operator=( const nsRefPtr<T>& rhs )
993 // copy assignment operator
995 assign_with_AddRef(rhs.mRawPtr);
996 return *this;
999 nsRefPtr<T>&
1000 operator=( T* rhs )
1001 // assign from a raw pointer (of the right type)
1003 assign_with_AddRef(rhs);
1004 return *this;
1007 nsRefPtr<T>&
1008 operator=( const already_AddRefed<T>& rhs )
1009 // assign from |dont_AddRef(expr)|
1011 assign_assuming_AddRef(rhs.mRawPtr);
1012 return *this;
1015 // Other pointer operators
1017 void
1018 swap( nsRefPtr<T>& rhs )
1019 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1021 T* temp = rhs.mRawPtr;
1022 rhs.mRawPtr = mRawPtr;
1023 mRawPtr = temp;
1026 void
1027 swap( T*& rhs )
1028 // ...exchange ownership with |rhs|; can save a pair of refcount operations
1030 T* temp = rhs;
1031 rhs = mRawPtr;
1032 mRawPtr = temp;
1035 already_AddRefed<T>
1036 forget()
1037 // return the value of mRawPtr and null out mRawPtr. Useful for
1038 // already_AddRefed return values.
1040 T* temp = 0;
1041 swap(temp);
1042 return temp;
1045 void
1046 forget( T** rhs )
1047 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
1048 // Useful to avoid unnecessary AddRef/Release pairs with "out"
1049 // parameters.
1051 NS_ASSERTION(rhs, "Null pointer passed to forget!");
1052 *rhs = 0;
1053 swap(*rhs);
1057 get() const
1059 Prefer the implicit conversion provided automatically by |operator T*() const|.
1060 Use |get()| to resolve ambiguity or to get a castable pointer.
1063 return const_cast<T*>(mRawPtr);
1066 operator T*() const
1068 ...makes an |nsRefPtr| act like its underlying raw pointer type whenever it
1069 is used in a context where a raw pointer is expected. It is this operator
1070 that makes an |nsRefPtr| substitutable for a raw pointer.
1072 Prefer the implicit use of this operator to calling |get()|, except where
1073 necessary to resolve ambiguity.
1076 return get();
1080 operator->() const
1082 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
1083 return get();
1086 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1087 // broken version for IRIX
1089 nsRefPtr<T>*
1090 get_address() const
1091 // This is not intended to be used by clients. See |address_of|
1092 // below.
1094 return const_cast<nsRefPtr<T>*>(this);
1097 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1099 nsRefPtr<T>*
1100 get_address()
1101 // This is not intended to be used by clients. See |address_of|
1102 // below.
1104 return this;
1107 const nsRefPtr<T>*
1108 get_address() const
1109 // This is not intended to be used by clients. See |address_of|
1110 // below.
1112 return this;
1115 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1117 public:
1119 operator*() const
1121 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*().");
1122 return *get();
1126 StartAssignment()
1128 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1129 return reinterpret_cast<T**>(begin_assignment());
1130 #else
1131 assign_assuming_AddRef(0);
1132 return reinterpret_cast<T**>(&mRawPtr);
1133 #endif
1137 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1139 // This is the broken version for IRIX, which can't handle the version below.
1141 template <class T>
1142 inline
1143 nsRefPtr<T>*
1144 address_of( const nsRefPtr<T>& aPtr )
1146 return aPtr.get_address();
1149 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1151 template <class T>
1152 inline
1153 nsRefPtr<T>*
1154 address_of( nsRefPtr<T>& aPtr )
1156 return aPtr.get_address();
1159 template <class T>
1160 inline
1161 const nsRefPtr<T>*
1162 address_of( const nsRefPtr<T>& aPtr )
1164 return aPtr.get_address();
1167 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1169 template <class T>
1170 class nsRefPtrGetterAddRefs
1174 This class is designed to be used for anonymous temporary objects in the
1175 argument list of calls that return COM interface pointers, e.g.,
1177 nsRefPtr<IFoo> fooP;
1178 ...->GetAddRefedPointer(getter_AddRefs(fooP))
1180 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1182 When initialized with a |nsRefPtr|, as in the example above, it returns
1183 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
1184 outer call (|GetAddRefedPointer| in this case) can fill in.
1186 This type should be a nested class inside |nsRefPtr<T>|.
1189 public:
1190 explicit
1191 nsRefPtrGetterAddRefs( nsRefPtr<T>& aSmartPtr )
1192 : mTargetSmartPtr(aSmartPtr)
1194 // nothing else to do
1197 operator void**()
1199 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1202 operator T**()
1204 return mTargetSmartPtr.StartAssignment();
1208 operator*()
1210 return *(mTargetSmartPtr.StartAssignment());
1213 private:
1214 nsRefPtr<T>& mTargetSmartPtr;
1217 template <class T>
1218 inline
1219 nsRefPtrGetterAddRefs<T>
1220 getter_AddRefs( nsRefPtr<T>& aSmartPtr )
1222 Used around a |nsRefPtr| when
1223 ...makes the class |nsRefPtrGetterAddRefs<T>| invisible.
1226 return nsRefPtrGetterAddRefs<T>(aSmartPtr);
1231 // Comparing two |nsRefPtr|s
1233 template <class T, class U>
1234 inline
1235 NSCAP_BOOL
1236 operator==( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
1238 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
1242 template <class T, class U>
1243 inline
1244 NSCAP_BOOL
1245 operator!=( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
1247 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
1251 // Comparing an |nsRefPtr| to a raw pointer
1253 template <class T, class U>
1254 inline
1255 NSCAP_BOOL
1256 operator==( const nsRefPtr<T>& lhs, const U* rhs )
1258 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
1261 template <class T, class U>
1262 inline
1263 NSCAP_BOOL
1264 operator==( const U* lhs, const nsRefPtr<T>& rhs )
1266 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
1269 template <class T, class U>
1270 inline
1271 NSCAP_BOOL
1272 operator!=( const nsRefPtr<T>& lhs, const U* rhs )
1274 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
1277 template <class T, class U>
1278 inline
1279 NSCAP_BOOL
1280 operator!=( const U* lhs, const nsRefPtr<T>& rhs )
1282 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
1285 // To avoid ambiguities caused by the presence of builtin |operator==|s
1286 // creating a situation where one of the |operator==| defined above
1287 // has a better conversion for one argument and the builtin has a
1288 // better conversion for the other argument, define additional
1289 // |operator==| without the |const| on the raw pointer.
1290 // See bug 65664 for details.
1292 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1293 template <class T, class U>
1294 inline
1295 NSCAP_BOOL
1296 operator==( const nsRefPtr<T>& lhs, U* rhs )
1298 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
1301 template <class T, class U>
1302 inline
1303 NSCAP_BOOL
1304 operator==( U* lhs, const nsRefPtr<T>& rhs )
1306 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
1309 template <class T, class U>
1310 inline
1311 NSCAP_BOOL
1312 operator!=( const nsRefPtr<T>& lhs, U* rhs )
1314 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
1317 template <class T, class U>
1318 inline
1319 NSCAP_BOOL
1320 operator!=( U* lhs, const nsRefPtr<T>& rhs )
1322 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
1324 #endif
1328 // Comparing an |nsRefPtr| to |0|
1330 template <class T>
1331 inline
1332 NSCAP_BOOL
1333 operator==( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
1334 // specifically to allow |smartPtr == 0|
1336 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1339 template <class T>
1340 inline
1341 NSCAP_BOOL
1342 operator==( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
1343 // specifically to allow |0 == smartPtr|
1345 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1348 template <class T>
1349 inline
1350 NSCAP_BOOL
1351 operator!=( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
1352 // specifically to allow |smartPtr != 0|
1354 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
1357 template <class T>
1358 inline
1359 NSCAP_BOOL
1360 operator!=( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
1361 // specifically to allow |0 != smartPtr|
1363 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
1367 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1369 // We need to explicitly define comparison operators for `int'
1370 // because the compiler is lame.
1372 template <class T>
1373 inline
1374 NSCAP_BOOL
1375 operator==( const nsRefPtr<T>& lhs, int rhs )
1376 // specifically to allow |smartPtr == 0|
1378 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
1381 template <class T>
1382 inline
1383 NSCAP_BOOL
1384 operator==( int lhs, const nsRefPtr<T>& rhs )
1385 // specifically to allow |0 == smartPtr|
1387 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
1390 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1392 /*****************************************************************************/
1394 #endif // !defined(nsAutoPtr_h___)