Back to index

lightning-sunbird  0.9+nobinonly
nsAutoPtr.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Scott Collins <scc@mozilla.org> (original author of nsCOMPtr)
00024  *   L. David Baron <dbaron@dbaron.org>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifndef nsAutoPtr_h___
00041 #define nsAutoPtr_h___
00042 
00043   // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
00044 #ifndef nsCOMPtr_h___
00045   // For |already_AddRefed|, |nsDerivedSafe|, |NSCAP_Zero|,
00046   // |NSCAP_DONT_PROVIDE_NONCONST_OPEQ|,
00047   // |NSCAP_FEATURE_INLINE_STARTASSIGNMENT|
00048 #include "nsCOMPtr.h"
00049 #endif
00050 
00051 /*****************************************************************************/
00052 
00053 // template <class T> class nsAutoPtrGetterTransfers;
00054 
00055 template <class T>
00056 class nsAutoPtr
00057   {
00058     private:
00059       void**
00060       begin_assignment()
00061         {
00062           assign(0);
00063           return NS_REINTERPRET_CAST(void**, &mRawPtr);
00064         }
00065 
00066       void
00067       assign( T* newPtr )
00068         {
00069           T* oldPtr = mRawPtr;
00070           mRawPtr = newPtr;
00071           delete oldPtr;
00072         }
00073 
00074       // |class Ptr| helps us prevent implicit "copy construction"
00075       // through |operator T*() const| from a |const nsAutoPtr<T>|
00076       // because two implicit conversions in a row aren't allowed.
00077       // It still allows assignment from T* through implicit conversion
00078       // from |T*| to |nsAutoPtr<T>::Ptr|
00079       class Ptr
00080         {
00081           public:
00082             Ptr( T* aPtr )
00083                   : mPtr(aPtr)
00084               {
00085               }
00086 
00087             operator T*() const
00088               {
00089                 return mPtr;
00090               }
00091 
00092           private:
00093             T* mPtr;
00094         };
00095 
00096     private:
00097       T* mRawPtr;
00098 
00099     public:
00100       typedef T element_type;
00101       
00102      ~nsAutoPtr()
00103         {
00104           delete mRawPtr;
00105         }
00106 
00107         // Constructors
00108 
00109       nsAutoPtr()
00110             : mRawPtr(0)
00111           // default constructor
00112         {
00113         }
00114 
00115       nsAutoPtr( Ptr aRawPtr )
00116             : mRawPtr(aRawPtr)
00117           // construct from a raw pointer (of the right type)
00118         {
00119         }
00120 
00121       nsAutoPtr( nsAutoPtr<T>& aSmartPtr )
00122             : mRawPtr( aSmartPtr.forget() )
00123           // Construct by transferring ownership from another smart pointer.
00124         {
00125         }
00126 
00127 
00128         // Assignment operators
00129 
00130       nsAutoPtr<T>&
00131       operator=( T* rhs )
00132           // assign from a raw pointer (of the right type)
00133         {
00134           assign(rhs);
00135           return *this;
00136         }
00137 
00138       nsAutoPtr<T>& operator=( nsAutoPtr<T>& rhs )
00139           // assign by transferring ownership from another smart pointer.
00140         {
00141           assign(rhs.forget());
00142           return *this;
00143         }
00144 
00145         // Other pointer operators
00146 
00147       T*
00148       get() const
00149           /*
00150             Prefer the implicit conversion provided automatically by
00151             |operator T*() const|.  Use |get()| _only_ to resolve
00152             ambiguity.
00153           */
00154         {
00155           return mRawPtr;
00156         }
00157 
00158       operator T*() const
00159           /*
00160             ...makes an |nsAutoPtr| act like its underlying raw pointer
00161             type  whenever it is used in a context where a raw pointer
00162             is expected.  It is this operator that makes an |nsAutoPtr|
00163             substitutable for a raw pointer.
00164 
00165             Prefer the implicit use of this operator to calling |get()|,
00166             except where necessary to resolve ambiguity.
00167           */
00168         {
00169           return get();
00170         }
00171 
00172       T*
00173       forget()
00174         {
00175           T* temp = mRawPtr;
00176           mRawPtr = 0;
00177           return temp;
00178         }
00179 
00180       T*
00181       operator->() const
00182         {
00183           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->().");
00184           return get();
00185         }
00186 
00187 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
00188   // broken version for IRIX
00189 
00190       nsAutoPtr<T>*
00191       get_address() const
00192           // This is not intended to be used by clients.  See |address_of|
00193           // below.
00194         {
00195           return NS_CONST_CAST(nsAutoPtr<T>*, this);
00196         }
00197 
00198 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00199 
00200       nsAutoPtr<T>*
00201       get_address()
00202           // This is not intended to be used by clients.  See |address_of|
00203           // below.
00204         {
00205           return this;
00206         }
00207 
00208       const nsAutoPtr<T>*
00209       get_address() const
00210           // This is not intended to be used by clients.  See |address_of|
00211           // below.
00212         {
00213           return this;
00214         }
00215 
00216 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00217 
00218     public:
00219       T&
00220       operator*() const
00221         {
00222           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*().");
00223           return *get();
00224         }
00225 
00226       T**
00227       StartAssignment()
00228         {
00229 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
00230           return NS_REINTERPRET_CAST(T**, begin_assignment());
00231 #else
00232           assign(0);
00233           return NS_REINTERPRET_CAST(T**, &mRawPtr);
00234 #endif
00235         }
00236   };
00237 
00238 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
00239 
00240 // This is the broken version for IRIX, which can't handle the version below.
00241 
00242 template <class T>
00243 inline
00244 nsAutoPtr<T>*
00245 address_of( const nsAutoPtr<T>& aPtr )
00246   {
00247     return aPtr.get_address();
00248   }
00249 
00250 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00251 
00252 template <class T>
00253 inline
00254 nsAutoPtr<T>*
00255 address_of( nsAutoPtr<T>& aPtr )
00256   {
00257     return aPtr.get_address();
00258   }
00259 
00260 template <class T>
00261 inline
00262 const nsAutoPtr<T>*
00263 address_of( const nsAutoPtr<T>& aPtr )
00264   {
00265     return aPtr.get_address();
00266   }
00267 
00268 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00269 
00270 template <class T>
00271 class nsAutoPtrGetterTransfers
00272     /*
00273       ...
00274 
00275       This class is designed to be used for anonymous temporary objects in the
00276       argument list of calls that return COM interface pointers, e.g.,
00277 
00278         nsAutoPtr<IFoo> fooP;
00279         ...->GetTransferedPointer(getter_Transfers(fooP))
00280 
00281       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_Transfers()| instead.
00282 
00283       When initialized with a |nsAutoPtr|, as in the example above, it returns
00284       a |void**|, a |T**|, or an |nsISupports**| as needed, that the
00285       outer call (|GetTransferedPointer| in this case) can fill in.
00286 
00287       This type should be a nested class inside |nsAutoPtr<T>|.
00288     */
00289   {
00290     public:
00291       explicit
00292       nsAutoPtrGetterTransfers( nsAutoPtr<T>& aSmartPtr )
00293           : mTargetSmartPtr(aSmartPtr)
00294         {
00295           // nothing else to do
00296         }
00297 
00298       operator void**()
00299         {
00300           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
00301         }
00302 
00303       operator T**()
00304         {
00305           return mTargetSmartPtr.StartAssignment();
00306         }
00307 
00308       T*&
00309       operator*()
00310         {
00311           return *(mTargetSmartPtr.StartAssignment());
00312         }
00313 
00314     private:
00315       nsAutoPtr<T>& mTargetSmartPtr;
00316   };
00317 
00318 template <class T>
00319 inline
00320 nsAutoPtrGetterTransfers<T>
00321 getter_Transfers( nsAutoPtr<T>& aSmartPtr )
00322     /*
00323       Used around a |nsAutoPtr| when 
00324       ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
00325     */
00326   {
00327     return nsAutoPtrGetterTransfers<T>(aSmartPtr);
00328   }
00329 
00330 
00331 
00332   // Comparing two |nsAutoPtr|s
00333 
00334 template <class T, class U>
00335 inline
00336 NSCAP_BOOL
00337 operator==( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
00338   {
00339     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
00340   }
00341 
00342 
00343 template <class T, class U>
00344 inline
00345 NSCAP_BOOL
00346 operator!=( const nsAutoPtr<T>& lhs, const nsAutoPtr<U>& rhs )
00347   {
00348     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
00349   }
00350 
00351 
00352   // Comparing an |nsAutoPtr| to a raw pointer
00353 
00354 template <class T, class U>
00355 inline
00356 NSCAP_BOOL
00357 operator==( const nsAutoPtr<T>& lhs, const U* rhs )
00358   {
00359     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
00360   }
00361 
00362 template <class T, class U>
00363 inline
00364 NSCAP_BOOL
00365 operator==( const U* lhs, const nsAutoPtr<T>& rhs )
00366   {
00367     return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
00368   }
00369 
00370 template <class T, class U>
00371 inline
00372 NSCAP_BOOL
00373 operator!=( const nsAutoPtr<T>& lhs, const U* rhs )
00374   {
00375     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
00376   }
00377 
00378 template <class T, class U>
00379 inline
00380 NSCAP_BOOL
00381 operator!=( const U* lhs, const nsAutoPtr<T>& rhs )
00382   {
00383     return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
00384   }
00385 
00386   // To avoid ambiguities caused by the presence of builtin |operator==|s
00387   // creating a situation where one of the |operator==| defined above
00388   // has a better conversion for one argument and the builtin has a
00389   // better conversion for the other argument, define additional
00390   // |operator==| without the |const| on the raw pointer.
00391   // See bug 65664 for details.
00392 
00393 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
00394 template <class T, class U>
00395 inline
00396 NSCAP_BOOL
00397 operator==( const nsAutoPtr<T>& lhs, U* rhs )
00398   {
00399     return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
00400   }
00401 
00402 template <class T, class U>
00403 inline
00404 NSCAP_BOOL
00405 operator==( U* lhs, const nsAutoPtr<T>& rhs )
00406   {
00407     return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
00408   }
00409 
00410 template <class T, class U>
00411 inline
00412 NSCAP_BOOL
00413 operator!=( const nsAutoPtr<T>& lhs, U* rhs )
00414   {
00415     return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
00416   }
00417 
00418 template <class T, class U>
00419 inline
00420 NSCAP_BOOL
00421 operator!=( U* lhs, const nsAutoPtr<T>& rhs )
00422   {
00423     return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
00424   }
00425 #endif
00426 
00427 
00428 
00429   // Comparing an |nsAutoPtr| to |0|
00430 
00431 template <class T>
00432 inline
00433 NSCAP_BOOL
00434 operator==( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
00435     // specifically to allow |smartPtr == 0|
00436   {
00437     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
00438   }
00439 
00440 template <class T>
00441 inline
00442 NSCAP_BOOL
00443 operator==( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
00444     // specifically to allow |0 == smartPtr|
00445   {
00446     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
00447   }
00448 
00449 template <class T>
00450 inline
00451 NSCAP_BOOL
00452 operator!=( const nsAutoPtr<T>& lhs, NSCAP_Zero* rhs )
00453     // specifically to allow |smartPtr != 0|
00454   {
00455     return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
00456   }
00457 
00458 template <class T>
00459 inline
00460 NSCAP_BOOL
00461 operator!=( NSCAP_Zero* lhs, const nsAutoPtr<T>& rhs )
00462     // specifically to allow |0 != smartPtr|
00463   {
00464     return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
00465   }
00466 
00467 
00468 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
00469 
00470   // We need to explicitly define comparison operators for `int'
00471   // because the compiler is lame.
00472 
00473 template <class T>
00474 inline
00475 NSCAP_BOOL
00476 operator==( const nsAutoPtr<T>& lhs, int rhs )
00477     // specifically to allow |smartPtr == 0|
00478   {
00479     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
00480   }
00481 
00482 template <class T>
00483 inline
00484 NSCAP_BOOL
00485 operator==( int lhs, const nsAutoPtr<T>& rhs )
00486     // specifically to allow |0 == smartPtr|
00487   {
00488     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
00489   }
00490 
00491 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
00492 
00493 /*****************************************************************************/
00494 
00495 // template <class T> class nsAutoArrayPtrGetterTransfers;
00496 
00497 template <class T>
00498 class nsAutoArrayPtr
00499   {
00500     private:
00501       void**
00502       begin_assignment()
00503         {
00504           assign(0);
00505           return NS_REINTERPRET_CAST(void**, &mRawPtr);
00506         }
00507 
00508       void
00509       assign( T* newPtr )
00510         {
00511           T* oldPtr = mRawPtr;
00512           mRawPtr = newPtr;
00513           delete [] oldPtr;
00514         }
00515 
00516     private:
00517       T* mRawPtr;
00518 
00519     public:
00520       typedef T element_type;
00521       
00522      ~nsAutoArrayPtr()
00523         {
00524           delete [] mRawPtr;
00525         }
00526 
00527         // Constructors
00528 
00529       nsAutoArrayPtr()
00530             : mRawPtr(0)
00531           // default constructor
00532         {
00533         }
00534 
00535       nsAutoArrayPtr( T* aRawPtr )
00536             : mRawPtr(aRawPtr)
00537           // construct from a raw pointer (of the right type)
00538         {
00539         }
00540 
00541       nsAutoArrayPtr( nsAutoArrayPtr<T>& aSmartPtr )
00542             : mRawPtr( aSmartPtr.forget() )
00543           // Construct by transferring ownership from another smart pointer.
00544         {
00545         }
00546 
00547 
00548         // Assignment operators
00549 
00550       nsAutoArrayPtr<T>&
00551       operator=( T* rhs )
00552           // assign from a raw pointer (of the right type)
00553         {
00554           assign(rhs);
00555           return *this;
00556         }
00557 
00558       nsAutoArrayPtr<T>& operator=( nsAutoArrayPtr<T>& rhs )
00559           // assign by transferring ownership from another smart pointer.
00560         {
00561           assign(rhs.forget());
00562           return *this;
00563         }
00564 
00565         // Other pointer operators
00566 
00567       T*
00568       get() const
00569           /*
00570             Prefer the implicit conversion provided automatically by
00571             |operator T*() const|.  Use |get()| _only_ to resolve
00572             ambiguity.
00573           */
00574         {
00575           return mRawPtr;
00576         }
00577 
00578       operator T*() const
00579           /*
00580             ...makes an |nsAutoArrayPtr| act like its underlying raw pointer
00581             type  whenever it is used in a context where a raw pointer
00582             is expected.  It is this operator that makes an |nsAutoArrayPtr|
00583             substitutable for a raw pointer.
00584 
00585             Prefer the implicit use of this operator to calling |get()|,
00586             except where necessary to resolve ambiguity.
00587           */
00588         {
00589           return get();
00590         }
00591 
00592       T*
00593       forget()
00594         {
00595           T* temp = mRawPtr;
00596           mRawPtr = 0;
00597           return temp;
00598         }
00599 
00600       T*
00601       operator->() const
00602         {
00603           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->().");
00604           return get();
00605         }
00606 
00607 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
00608   // broken version for IRIX
00609 
00610       nsAutoArrayPtr<T>*
00611       get_address() const
00612           // This is not intended to be used by clients.  See |address_of|
00613           // below.
00614         {
00615           return NS_CONST_CAST(nsAutoArrayPtr<T>*, this);
00616         }
00617 
00618 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00619 
00620       nsAutoArrayPtr<T>*
00621       get_address()
00622           // This is not intended to be used by clients.  See |address_of|
00623           // below.
00624         {
00625           return this;
00626         }
00627 
00628       const nsAutoArrayPtr<T>*
00629       get_address() const
00630           // This is not intended to be used by clients.  See |address_of|
00631           // below.
00632         {
00633           return this;
00634         }
00635 
00636 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00637 
00638     public:
00639       T&
00640       operator*() const
00641         {
00642           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*().");
00643           return *get();
00644         }
00645 
00646       T**
00647       StartAssignment()
00648         {
00649 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
00650           return NS_REINTERPRET_CAST(T**, begin_assignment());
00651 #else
00652           assign(0);
00653           return NS_REINTERPRET_CAST(T**, &mRawPtr);
00654 #endif
00655         }
00656   };
00657 
00658 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
00659 
00660 // This is the broken version for IRIX, which can't handle the version below.
00661 
00662 template <class T>
00663 inline
00664 nsAutoArrayPtr<T>*
00665 address_of( const nsAutoArrayPtr<T>& aPtr )
00666   {
00667     return aPtr.get_address();
00668   }
00669 
00670 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00671 
00672 template <class T>
00673 inline
00674 nsAutoArrayPtr<T>*
00675 address_of( nsAutoArrayPtr<T>& aPtr )
00676   {
00677     return aPtr.get_address();
00678   }
00679 
00680 template <class T>
00681 inline
00682 const nsAutoArrayPtr<T>*
00683 address_of( const nsAutoArrayPtr<T>& aPtr )
00684   {
00685     return aPtr.get_address();
00686   }
00687 
00688 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
00689 
00690 template <class T>
00691 class nsAutoArrayPtrGetterTransfers
00692     /*
00693       ...
00694 
00695       This class is designed to be used for anonymous temporary objects in the
00696       argument list of calls that return COM interface pointers, e.g.,
00697 
00698         nsAutoArrayPtr<IFoo> fooP;
00699         ...->GetTransferedPointer(getter_Transfers(fooP))
00700 
00701       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_Transfers()| instead.
00702 
00703       When initialized with a |nsAutoArrayPtr|, as in the example above, it returns
00704       a |void**|, a |T**|, or an |nsISupports**| as needed, that the
00705       outer call (|GetTransferedPointer| in this case) can fill in.
00706 
00707       This type should be a nested class inside |nsAutoArrayPtr<T>|.
00708     */
00709   {
00710     public:
00711       explicit
00712       nsAutoArrayPtrGetterTransfers( nsAutoArrayPtr<T>& aSmartPtr )
00713           : mTargetSmartPtr(aSmartPtr)
00714         {
00715           // nothing else to do
00716         }
00717 
00718       operator void**()
00719         {
00720           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
00721         }
00722 
00723       operator T**()
00724         {
00725           return mTargetSmartPtr.StartAssignment();
00726         }
00727 
00728       T*&
00729       operator*()
00730         {
00731           return *(mTargetSmartPtr.StartAssignment());
00732         }
00733 
00734     private:
00735       nsAutoArrayPtr<T>& mTargetSmartPtr;
00736   };
00737 
00738 template <class T>
00739 inline
00740 nsAutoArrayPtrGetterTransfers<T>
00741 getter_Transfers( nsAutoArrayPtr<T>& aSmartPtr )
00742     /*
00743       Used around a |nsAutoArrayPtr| when 
00744       ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible.
00745     */
00746   {
00747     return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr);
00748   }
00749 
00750 
00751 
00752   // Comparing two |nsAutoArrayPtr|s
00753 
00754 template <class T, class U>
00755 inline
00756 NSCAP_BOOL
00757 operator==( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
00758   {
00759     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
00760   }
00761 
00762 
00763 template <class T, class U>
00764 inline
00765 NSCAP_BOOL
00766 operator!=( const nsAutoArrayPtr<T>& lhs, const nsAutoArrayPtr<U>& rhs )
00767   {
00768     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
00769   }
00770 
00771 
00772   // Comparing an |nsAutoArrayPtr| to a raw pointer
00773 
00774 template <class T, class U>
00775 inline
00776 NSCAP_BOOL
00777 operator==( const nsAutoArrayPtr<T>& lhs, const U* rhs )
00778   {
00779     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
00780   }
00781 
00782 template <class T, class U>
00783 inline
00784 NSCAP_BOOL
00785 operator==( const U* lhs, const nsAutoArrayPtr<T>& rhs )
00786   {
00787     return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
00788   }
00789 
00790 template <class T, class U>
00791 inline
00792 NSCAP_BOOL
00793 operator!=( const nsAutoArrayPtr<T>& lhs, const U* rhs )
00794   {
00795     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
00796   }
00797 
00798 template <class T, class U>
00799 inline
00800 NSCAP_BOOL
00801 operator!=( const U* lhs, const nsAutoArrayPtr<T>& rhs )
00802   {
00803     return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
00804   }
00805 
00806   // To avoid ambiguities caused by the presence of builtin |operator==|s
00807   // creating a situation where one of the |operator==| defined above
00808   // has a better conversion for one argument and the builtin has a
00809   // better conversion for the other argument, define additional
00810   // |operator==| without the |const| on the raw pointer.
00811   // See bug 65664 for details.
00812 
00813 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
00814 template <class T, class U>
00815 inline
00816 NSCAP_BOOL
00817 operator==( const nsAutoArrayPtr<T>& lhs, U* rhs )
00818   {
00819     return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
00820   }
00821 
00822 template <class T, class U>
00823 inline
00824 NSCAP_BOOL
00825 operator==( U* lhs, const nsAutoArrayPtr<T>& rhs )
00826   {
00827     return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
00828   }
00829 
00830 template <class T, class U>
00831 inline
00832 NSCAP_BOOL
00833 operator!=( const nsAutoArrayPtr<T>& lhs, U* rhs )
00834   {
00835     return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
00836   }
00837 
00838 template <class T, class U>
00839 inline
00840 NSCAP_BOOL
00841 operator!=( U* lhs, const nsAutoArrayPtr<T>& rhs )
00842   {
00843     return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
00844   }
00845 #endif
00846 
00847 
00848 
00849   // Comparing an |nsAutoArrayPtr| to |0|
00850 
00851 template <class T>
00852 inline
00853 NSCAP_BOOL
00854 operator==( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
00855     // specifically to allow |smartPtr == 0|
00856   {
00857     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
00858   }
00859 
00860 template <class T>
00861 inline
00862 NSCAP_BOOL
00863 operator==( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
00864     // specifically to allow |0 == smartPtr|
00865   {
00866     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
00867   }
00868 
00869 template <class T>
00870 inline
00871 NSCAP_BOOL
00872 operator!=( const nsAutoArrayPtr<T>& lhs, NSCAP_Zero* rhs )
00873     // specifically to allow |smartPtr != 0|
00874   {
00875     return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
00876   }
00877 
00878 template <class T>
00879 inline
00880 NSCAP_BOOL
00881 operator!=( NSCAP_Zero* lhs, const nsAutoArrayPtr<T>& rhs )
00882     // specifically to allow |0 != smartPtr|
00883   {
00884     return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
00885   }
00886 
00887 
00888 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
00889 
00890   // We need to explicitly define comparison operators for `int'
00891   // because the compiler is lame.
00892 
00893 template <class T>
00894 inline
00895 NSCAP_BOOL
00896 operator==( const nsAutoArrayPtr<T>& lhs, int rhs )
00897     // specifically to allow |smartPtr == 0|
00898   {
00899     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
00900   }
00901 
00902 template <class T>
00903 inline
00904 NSCAP_BOOL
00905 operator==( int lhs, const nsAutoArrayPtr<T>& rhs )
00906     // specifically to allow |0 == smartPtr|
00907   {
00908     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
00909   }
00910 
00911 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
00912 
00913 
00914 /*****************************************************************************/
00915 
00916 // template <class T> class nsRefPtrGetterAddRefs;
00917 
00918 template <class T>
00919 class nsRefPtr
00920   {
00921     private:
00922 
00923       void
00924       assign_with_AddRef( T* rawPtr )
00925         {
00926           if ( rawPtr )
00927             rawPtr->AddRef();
00928           assign_assuming_AddRef(rawPtr);
00929         }
00930 
00931       void**
00932       begin_assignment()
00933         {
00934           assign_assuming_AddRef(0);
00935           return NS_REINTERPRET_CAST(void**, &mRawPtr);
00936         }
00937 
00938       void
00939       assign_assuming_AddRef( T* newPtr )
00940         {
00941           T* oldPtr = mRawPtr;
00942           mRawPtr = newPtr;
00943           if ( oldPtr )
00944             oldPtr->Release();
00945         }
00946 
00947     private:
00948       T* mRawPtr;
00949 
00950     public:
00951       typedef T element_type;
00952       
00953      ~nsRefPtr()
00954         {
00955           if ( mRawPtr )
00956             mRawPtr->Release();
00957         }
00958 
00959         // Constructors
00960 
00961       nsRefPtr()
00962             : mRawPtr(0)
00963           // default constructor
00964         {
00965         }
00966 
00967       nsRefPtr( const nsRefPtr<T>& aSmartPtr )
00968             : mRawPtr(aSmartPtr.mRawPtr)
00969           // copy-constructor
00970         {
00971           if ( mRawPtr )
00972             mRawPtr->AddRef();
00973         }
00974 
00975       nsRefPtr( T* aRawPtr )
00976             : mRawPtr(aRawPtr)
00977           // construct from a raw pointer (of the right type)
00978         {
00979           if ( mRawPtr )
00980             mRawPtr->AddRef();
00981         }
00982 
00983       nsRefPtr( const already_AddRefed<T>& aSmartPtr )
00984             : mRawPtr(aSmartPtr.mRawPtr)
00985           // construct from |dont_AddRef(expr)|
00986         {
00987         }
00988 
00989         // Assignment operators
00990 
00991       nsRefPtr<T>&
00992       operator=( const nsRefPtr<T>& rhs )
00993           // copy assignment operator
00994         {
00995           assign_with_AddRef(rhs.mRawPtr);
00996           return *this;
00997         }
00998 
00999       nsRefPtr<T>&
01000       operator=( T* rhs )
01001           // assign from a raw pointer (of the right type)
01002         {
01003           assign_with_AddRef(rhs);
01004           return *this;
01005         }
01006 
01007       nsRefPtr<T>&
01008       operator=( const already_AddRefed<T>& rhs )
01009           // assign from |dont_AddRef(expr)|
01010         {
01011           assign_assuming_AddRef(rhs.mRawPtr);
01012           return *this;
01013         }
01014 
01015         // Other pointer operators
01016 
01017       void
01018       swap( nsRefPtr<T>& rhs )
01019           // ...exchange ownership with |rhs|; can save a pair of refcount operations
01020         {
01021           T* temp = rhs.mRawPtr;
01022           rhs.mRawPtr = mRawPtr;
01023           mRawPtr = temp;
01024         }
01025 
01026       void
01027       swap( T*& rhs )
01028           // ...exchange ownership with |rhs|; can save a pair of refcount operations
01029         {
01030           T* temp = rhs;
01031           rhs = mRawPtr;
01032           mRawPtr = temp;
01033         }
01034 
01035       nsDerivedSafe<T>*
01036       get() const
01037           /*
01038             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
01039              Use |get()| _only_ to resolve ambiguity.
01040 
01041             Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
01042           */
01043         {
01044           return NS_CONST_CAST(nsDerivedSafe<T>*,
01045                         NS_REINTERPRET_CAST(const nsDerivedSafe<T>*, mRawPtr));
01046         }
01047 
01048       operator nsDerivedSafe<T>*() const
01049           /*
01050             ...makes an |nsRefPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
01051               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
01052               that makes an |nsRefPtr| substitutable for a raw pointer.
01053 
01054             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
01055           */
01056         {
01057           return get();
01058         }
01059 
01060       nsDerivedSafe<T>*
01061       operator->() const
01062         {
01063           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->().");
01064           return get();
01065         }
01066 
01067 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
01068   // broken version for IRIX
01069 
01070       nsRefPtr<T>*
01071       get_address() const
01072           // This is not intended to be used by clients.  See |address_of|
01073           // below.
01074         {
01075           return NS_CONST_CAST(nsRefPtr<T>*, this);
01076         }
01077 
01078 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01079 
01080       nsRefPtr<T>*
01081       get_address()
01082           // This is not intended to be used by clients.  See |address_of|
01083           // below.
01084         {
01085           return this;
01086         }
01087 
01088       const nsRefPtr<T>*
01089       get_address() const
01090           // This is not intended to be used by clients.  See |address_of|
01091           // below.
01092         {
01093           return this;
01094         }
01095 
01096 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01097 
01098     public:
01099       nsDerivedSafe<T>&
01100       operator*() const
01101         {
01102           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*().");
01103           return *get();
01104         }
01105 
01106       T**
01107       StartAssignment()
01108         {
01109 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
01110           return NS_REINTERPRET_CAST(T**, begin_assignment());
01111 #else
01112           assign_assuming_AddRef(0);
01113           return NS_REINTERPRET_CAST(T**, &mRawPtr);
01114 #endif
01115         }
01116   };
01117 
01118 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
01119 
01120 // This is the broken version for IRIX, which can't handle the version below.
01121 
01122 template <class T>
01123 inline
01124 nsRefPtr<T>*
01125 address_of( const nsRefPtr<T>& aPtr )
01126   {
01127     return aPtr.get_address();
01128   }
01129 
01130 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01131 
01132 template <class T>
01133 inline
01134 nsRefPtr<T>*
01135 address_of( nsRefPtr<T>& aPtr )
01136   {
01137     return aPtr.get_address();
01138   }
01139 
01140 template <class T>
01141 inline
01142 const nsRefPtr<T>*
01143 address_of( const nsRefPtr<T>& aPtr )
01144   {
01145     return aPtr.get_address();
01146   }
01147 
01148 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
01149 
01150 template <class T>
01151 class nsRefPtrGetterAddRefs
01152     /*
01153       ...
01154 
01155       This class is designed to be used for anonymous temporary objects in the
01156       argument list of calls that return COM interface pointers, e.g.,
01157 
01158         nsRefPtr<IFoo> fooP;
01159         ...->GetAddRefedPointer(getter_AddRefs(fooP))
01160 
01161       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
01162 
01163       When initialized with a |nsRefPtr|, as in the example above, it returns
01164       a |void**|, a |T**|, or an |nsISupports**| as needed, that the
01165       outer call (|GetAddRefedPointer| in this case) can fill in.
01166 
01167       This type should be a nested class inside |nsRefPtr<T>|.
01168     */
01169   {
01170     public:
01171       explicit
01172       nsRefPtrGetterAddRefs( nsRefPtr<T>& aSmartPtr )
01173           : mTargetSmartPtr(aSmartPtr)
01174         {
01175           // nothing else to do
01176         }
01177 
01178       operator void**()
01179         {
01180           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
01181         }
01182 
01183       operator T**()
01184         {
01185           return mTargetSmartPtr.StartAssignment();
01186         }
01187 
01188       T*&
01189       operator*()
01190         {
01191           return *(mTargetSmartPtr.StartAssignment());
01192         }
01193 
01194     private:
01195       nsRefPtr<T>& mTargetSmartPtr;
01196   };
01197 
01198 template <class T>
01199 inline
01200 nsRefPtrGetterAddRefs<T>
01201 getter_AddRefs( nsRefPtr<T>& aSmartPtr )
01202     /*
01203       Used around a |nsRefPtr| when 
01204       ...makes the class |nsRefPtrGetterAddRefs<T>| invisible.
01205     */
01206   {
01207     return nsRefPtrGetterAddRefs<T>(aSmartPtr);
01208   }
01209 
01210 
01211 
01212   // Comparing two |nsRefPtr|s
01213 
01214 template <class T, class U>
01215 inline
01216 NSCAP_BOOL
01217 operator==( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
01218   {
01219     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
01220   }
01221 
01222 
01223 template <class T, class U>
01224 inline
01225 NSCAP_BOOL
01226 operator!=( const nsRefPtr<T>& lhs, const nsRefPtr<U>& rhs )
01227   {
01228     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
01229   }
01230 
01231 
01232   // Comparing an |nsRefPtr| to a raw pointer
01233 
01234 template <class T, class U>
01235 inline
01236 NSCAP_BOOL
01237 operator==( const nsRefPtr<T>& lhs, const U* rhs )
01238   {
01239     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs);
01240   }
01241 
01242 template <class T, class U>
01243 inline
01244 NSCAP_BOOL
01245 operator==( const U* lhs, const nsRefPtr<T>& rhs )
01246   {
01247     return NS_STATIC_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
01248   }
01249 
01250 template <class T, class U>
01251 inline
01252 NSCAP_BOOL
01253 operator!=( const nsRefPtr<T>& lhs, const U* rhs )
01254   {
01255     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs);
01256   }
01257 
01258 template <class T, class U>
01259 inline
01260 NSCAP_BOOL
01261 operator!=( const U* lhs, const nsRefPtr<T>& rhs )
01262   {
01263     return NS_STATIC_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
01264   }
01265 
01266   // To avoid ambiguities caused by the presence of builtin |operator==|s
01267   // creating a situation where one of the |operator==| defined above
01268   // has a better conversion for one argument and the builtin has a
01269   // better conversion for the other argument, define additional
01270   // |operator==| without the |const| on the raw pointer.
01271   // See bug 65664 for details.
01272 
01273 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
01274 template <class T, class U>
01275 inline
01276 NSCAP_BOOL
01277 operator==( const nsRefPtr<T>& lhs, U* rhs )
01278   {
01279     return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
01280   }
01281 
01282 template <class T, class U>
01283 inline
01284 NSCAP_BOOL
01285 operator==( U* lhs, const nsRefPtr<T>& rhs )
01286   {
01287     return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
01288   }
01289 
01290 template <class T, class U>
01291 inline
01292 NSCAP_BOOL
01293 operator!=( const nsRefPtr<T>& lhs, U* rhs )
01294   {
01295     return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
01296   }
01297 
01298 template <class T, class U>
01299 inline
01300 NSCAP_BOOL
01301 operator!=( U* lhs, const nsRefPtr<T>& rhs )
01302   {
01303     return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
01304   }
01305 #endif
01306 
01307 
01308 
01309   // Comparing an |nsRefPtr| to |0|
01310 
01311 template <class T>
01312 inline
01313 NSCAP_BOOL
01314 operator==( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
01315     // specifically to allow |smartPtr == 0|
01316   {
01317     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
01318   }
01319 
01320 template <class T>
01321 inline
01322 NSCAP_BOOL
01323 operator==( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
01324     // specifically to allow |0 == smartPtr|
01325   {
01326     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
01327   }
01328 
01329 template <class T>
01330 inline
01331 NSCAP_BOOL
01332 operator!=( const nsRefPtr<T>& lhs, NSCAP_Zero* rhs )
01333     // specifically to allow |smartPtr != 0|
01334   {
01335     return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
01336   }
01337 
01338 template <class T>
01339 inline
01340 NSCAP_BOOL
01341 operator!=( NSCAP_Zero* lhs, const nsRefPtr<T>& rhs )
01342     // specifically to allow |0 != smartPtr|
01343   {
01344     return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
01345   }
01346 
01347 
01348 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
01349 
01350   // We need to explicitly define comparison operators for `int'
01351   // because the compiler is lame.
01352 
01353 template <class T>
01354 inline
01355 NSCAP_BOOL
01356 operator==( const nsRefPtr<T>& lhs, int rhs )
01357     // specifically to allow |smartPtr == 0|
01358   {
01359     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
01360   }
01361 
01362 template <class T>
01363 inline
01364 NSCAP_BOOL
01365 operator==( int lhs, const nsRefPtr<T>& rhs )
01366     // specifically to allow |0 == smartPtr|
01367   {
01368     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
01369   }
01370 
01371 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
01372 
01373 /*****************************************************************************/
01374 
01375 #endif // !defined(nsAutoPtr_h___)