/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsAutoPtr_h___ #define nsAutoPtr_h___ #include "nsCOMPtr.h" #include "nsCycleCollectionNoteChild.h" #include "mozilla/MemoryReporting.h" /*****************************************************************************/ // template class nsAutoPtrGetterTransfers; template class nsAutoPtr { private: void** begin_assignment() { assign(0); return reinterpret_cast(&mRawPtr); } void assign(T* aNewPtr) { T* oldPtr = mRawPtr; if (aNewPtr && aNewPtr == oldPtr) { NS_RUNTIMEABORT("Logic flaw in the caller"); } mRawPtr = aNewPtr; delete oldPtr; } // |class Ptr| helps us prevent implicit "copy construction" // through |operator T*() const| from a |const nsAutoPtr| // because two implicit conversions in a row aren't allowed. // It still allows assignment from T* through implicit conversion // from |T*| to |nsAutoPtr::Ptr| class Ptr { public: Ptr(T* aPtr) : mPtr(aPtr) { } operator T*() const { return mPtr; } private: T* mPtr; }; private: T* mRawPtr; public: typedef T element_type; ~nsAutoPtr() { delete mRawPtr; } // Constructors nsAutoPtr() : mRawPtr(0) // default constructor { } nsAutoPtr(Ptr aRawPtr) : mRawPtr(aRawPtr) // construct from a raw pointer (of the right type) { } // This constructor shouldn't exist; we should just use the && // constructor. nsAutoPtr(nsAutoPtr& aSmartPtr) : mRawPtr(aSmartPtr.forget()) // Construct by transferring ownership from another smart pointer. { } nsAutoPtr(nsAutoPtr&& aSmartPtr) : mRawPtr(aSmartPtr.forget()) // Construct by transferring ownership from another smart pointer. { } // Assignment operators nsAutoPtr& operator=(T* aRhs) // assign from a raw pointer (of the right type) { assign(aRhs); return *this; } nsAutoPtr& operator=(nsAutoPtr& aRhs) // assign by transferring ownership from another smart pointer. { assign(aRhs.forget()); return *this; } nsAutoPtr& operator=(nsAutoPtr&& aRhs) { assign(aRhs.forget()); return *this; } // Other pointer operators T* get() const /* Prefer the implicit conversion provided automatically by |operator T*() const|. Use |get()| _only_ to resolve ambiguity. */ { return mRawPtr; } operator T*() const /* ...makes an |nsAutoPtr| act like its underlying raw pointer type whenever it is used in a context where a raw pointer is expected. It is this operator that makes an |nsAutoPtr| substitutable for a raw pointer. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity. */ { return get(); } T* forget() { T* temp = mRawPtr; mRawPtr = 0; return temp; } T* operator->() const { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->()."); return get(); } // This operator is needed for gcc <= 4.0.* and for Sun Studio; it // causes internal compiler errors for some MSVC versions. (It's not // clear to me whether it should be needed.) #ifndef _MSC_VER template U& operator->*(U V::* aMember) { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator->*()."); return get()->*aMember; } #endif nsAutoPtr* get_address() // This is not intended to be used by clients. See |address_of| // below. { return this; } const nsAutoPtr* get_address() const // This is not intended to be used by clients. See |address_of| // below. { return this; } public: T& operator*() const { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoPtr with operator*()."); return *get(); } T** StartAssignment() { #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT return reinterpret_cast(begin_assignment()); #else assign(0); return reinterpret_cast(&mRawPtr); #endif } }; template inline nsAutoPtr* address_of(nsAutoPtr& aPtr) { return aPtr.get_address(); } template inline const nsAutoPtr* address_of(const nsAutoPtr& aPtr) { return aPtr.get_address(); } template class nsAutoPtrGetterTransfers /* ... This class is designed to be used for anonymous temporary objects in the argument list of calls that return COM interface pointers, e.g., nsAutoPtr fooP; ...->GetTransferedPointer(getter_Transfers(fooP)) DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead. When initialized with a |nsAutoPtr|, as in the example above, it returns a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|GetTransferedPointer| in this case) can fill in. This type should be a nested class inside |nsAutoPtr|. */ { public: explicit nsAutoPtrGetterTransfers(nsAutoPtr& aSmartPtr) : mTargetSmartPtr(aSmartPtr) { // nothing else to do } operator void**() { return reinterpret_cast(mTargetSmartPtr.StartAssignment()); } operator T**() { return mTargetSmartPtr.StartAssignment(); } T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); } private: nsAutoPtr& mTargetSmartPtr; }; template inline nsAutoPtrGetterTransfers getter_Transfers(nsAutoPtr& aSmartPtr) /* Used around a |nsAutoPtr| when ...makes the class |nsAutoPtrGetterTransfers| invisible. */ { return nsAutoPtrGetterTransfers(aSmartPtr); } // Comparing two |nsAutoPtr|s template inline bool operator==(const nsAutoPtr& aLhs, const nsAutoPtr& aRhs) { return static_cast(aLhs.get()) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoPtr& aLhs, const nsAutoPtr& aRhs) { return static_cast(aLhs.get()) != static_cast(aRhs.get()); } // Comparing an |nsAutoPtr| to a raw pointer template inline bool operator==(const nsAutoPtr& aLhs, const U* aRhs) { return static_cast(aLhs.get()) == static_cast(aRhs); } template inline bool operator==(const U* aLhs, const nsAutoPtr& aRhs) { return static_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoPtr& aLhs, const U* aRhs) { return static_cast(aLhs.get()) != static_cast(aRhs); } template inline bool operator!=(const U* aLhs, const nsAutoPtr& aRhs) { return static_cast(aLhs) != static_cast(aRhs.get()); } // To avoid ambiguities caused by the presence of builtin |operator==|s // creating a situation where one of the |operator==| defined above // has a better conversion for one argument and the builtin has a // better conversion for the other argument, define additional // |operator==| without the |const| on the raw pointer. // See bug 65664 for details. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ template inline bool operator==(const nsAutoPtr& aLhs, U* aRhs) { return static_cast(aLhs.get()) == const_cast(aRhs); } template inline bool operator==(U* aLhs, const nsAutoPtr& aRhs) { return const_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoPtr& aLhs, U* aRhs) { return static_cast(aLhs.get()) != const_cast(aRhs); } template inline bool operator!=(U* aLhs, const nsAutoPtr& aRhs) { return const_cast(aLhs) != static_cast(aRhs.get()); } #endif // Comparing an |nsAutoPtr| to |0| template inline bool operator==(const nsAutoPtr& aLhs, NSCAP_Zero* aRhs) // specifically to allow |smartPtr == 0| { return static_cast(aLhs.get()) == reinterpret_cast(aRhs); } template inline bool operator==(NSCAP_Zero* aLhs, const nsAutoPtr& aRhs) // specifically to allow |0 == smartPtr| { return reinterpret_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoPtr& aLhs, NSCAP_Zero* aRhs) // specifically to allow |smartPtr != 0| { return static_cast(aLhs.get()) != reinterpret_cast(aRhs); } template inline bool operator!=(NSCAP_Zero* aLhs, const nsAutoPtr& aRhs) // specifically to allow |0 != smartPtr| { return reinterpret_cast(aLhs) != static_cast(aRhs.get()); } #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO // We need to explicitly define comparison operators for `int' // because the compiler is lame. template inline bool operator==(const nsAutoPtr& aLhs, int aRhs) // specifically to allow |smartPtr == 0| { return static_cast(aLhs.get()) == reinterpret_cast(aRhs); } template inline bool operator==(int aLhs, const nsAutoPtr& aRhs) // specifically to allow |0 == smartPtr| { return reinterpret_cast(aLhs) == static_cast(aRhs.get()); } #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) /*****************************************************************************/ // template class nsAutoArrayPtrGetterTransfers; template class nsAutoArrayPtr { private: void** begin_assignment() { assign(0); return reinterpret_cast(&mRawPtr); } void assign(T* aNewPtr) { T* oldPtr = mRawPtr; mRawPtr = aNewPtr; delete [] oldPtr; } private: T* mRawPtr; public: typedef T element_type; ~nsAutoArrayPtr() { delete [] mRawPtr; } // Constructors nsAutoArrayPtr() : mRawPtr(0) // default constructor { } nsAutoArrayPtr(T* aRawPtr) : mRawPtr(aRawPtr) // construct from a raw pointer (of the right type) { } nsAutoArrayPtr(nsAutoArrayPtr& aSmartPtr) : mRawPtr(aSmartPtr.forget()) // Construct by transferring ownership from another smart pointer. { } // Assignment operators nsAutoArrayPtr& operator=(T* aRhs) // assign from a raw pointer (of the right type) { assign(aRhs); return *this; } nsAutoArrayPtr& operator=(nsAutoArrayPtr& aRhs) // assign by transferring ownership from another smart pointer. { assign(aRhs.forget()); return *this; } // Other pointer operators T* get() const /* Prefer the implicit conversion provided automatically by |operator T*() const|. Use |get()| _only_ to resolve ambiguity. */ { return mRawPtr; } operator T*() const /* ...makes an |nsAutoArrayPtr| act like its underlying raw pointer type whenever it is used in a context where a raw pointer is expected. It is this operator that makes an |nsAutoArrayPtr| substitutable for a raw pointer. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity. */ { return get(); } T* forget() { T* temp = mRawPtr; mRawPtr = 0; return temp; } T* operator->() const { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator->()."); return get(); } nsAutoArrayPtr* get_address() // This is not intended to be used by clients. See |address_of| // below. { return this; } const nsAutoArrayPtr* get_address() const // This is not intended to be used by clients. See |address_of| // below. { return this; } public: T& operator*() const { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsAutoArrayPtr with operator*()."); return *get(); } T** StartAssignment() { #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT return reinterpret_cast(begin_assignment()); #else assign(0); return reinterpret_cast(&mRawPtr); #endif } size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { return aMallocSizeOf(mRawPtr); } size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } }; template inline nsAutoArrayPtr* address_of(nsAutoArrayPtr& aPtr) { return aPtr.get_address(); } template inline const nsAutoArrayPtr* address_of(const nsAutoArrayPtr& aPtr) { return aPtr.get_address(); } template class nsAutoArrayPtrGetterTransfers /* ... This class is designed to be used for anonymous temporary objects in the argument list of calls that return COM interface pointers, e.g., nsAutoArrayPtr fooP; ...->GetTransferedPointer(getter_Transfers(fooP)) DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead. When initialized with a |nsAutoArrayPtr|, as in the example above, it returns a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|GetTransferedPointer| in this case) can fill in. This type should be a nested class inside |nsAutoArrayPtr|. */ { public: explicit nsAutoArrayPtrGetterTransfers(nsAutoArrayPtr& aSmartPtr) : mTargetSmartPtr(aSmartPtr) { // nothing else to do } operator void**() { return reinterpret_cast(mTargetSmartPtr.StartAssignment()); } operator T**() { return mTargetSmartPtr.StartAssignment(); } T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); } private: nsAutoArrayPtr& mTargetSmartPtr; }; template inline nsAutoArrayPtrGetterTransfers getter_Transfers(nsAutoArrayPtr& aSmartPtr) /* Used around a |nsAutoArrayPtr| when ...makes the class |nsAutoArrayPtrGetterTransfers| invisible. */ { return nsAutoArrayPtrGetterTransfers(aSmartPtr); } // Comparing two |nsAutoArrayPtr|s template inline bool operator==(const nsAutoArrayPtr& aLhs, const nsAutoArrayPtr& aRhs) { return static_cast(aLhs.get()) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoArrayPtr& aLhs, const nsAutoArrayPtr& aRhs) { return static_cast(aLhs.get()) != static_cast(aRhs.get()); } // Comparing an |nsAutoArrayPtr| to a raw pointer template inline bool operator==(const nsAutoArrayPtr& aLhs, const U* aRhs) { return static_cast(aLhs.get()) == static_cast(aRhs); } template inline bool operator==(const U* aLhs, const nsAutoArrayPtr& aRhs) { return static_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoArrayPtr& aLhs, const U* aRhs) { return static_cast(aLhs.get()) != static_cast(aRhs); } template inline bool operator!=(const U* aLhs, const nsAutoArrayPtr& aRhs) { return static_cast(aLhs) != static_cast(aRhs.get()); } // To avoid ambiguities caused by the presence of builtin |operator==|s // creating a situation where one of the |operator==| defined above // has a better conversion for one argument and the builtin has a // better conversion for the other argument, define additional // |operator==| without the |const| on the raw pointer. // See bug 65664 for details. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ template inline bool operator==(const nsAutoArrayPtr& aLhs, U* aRhs) { return static_cast(aLhs.get()) == const_cast(aRhs); } template inline bool operator==(U* aLhs, const nsAutoArrayPtr& aRhs) { return const_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoArrayPtr& aLhs, U* aRhs) { return static_cast(aLhs.get()) != const_cast(aRhs); } template inline bool operator!=(U* aLhs, const nsAutoArrayPtr& aRhs) { return const_cast(aLhs) != static_cast(aRhs.get()); } #endif // Comparing an |nsAutoArrayPtr| to |0| template inline bool operator==(const nsAutoArrayPtr& aLhs, NSCAP_Zero* aRhs) // specifically to allow |smartPtr == 0| { return static_cast(aLhs.get()) == reinterpret_cast(aRhs); } template inline bool operator==(NSCAP_Zero* aLhs, const nsAutoArrayPtr& aRhs) // specifically to allow |0 == smartPtr| { return reinterpret_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsAutoArrayPtr& aLhs, NSCAP_Zero* aRhs) // specifically to allow |smartPtr != 0| { return static_cast(aLhs.get()) != reinterpret_cast(aRhs); } template inline bool operator!=(NSCAP_Zero* aLhs, const nsAutoArrayPtr& aRhs) // specifically to allow |0 != smartPtr| { return reinterpret_cast(aLhs) != static_cast(aRhs.get()); } #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO // We need to explicitly define comparison operators for `int' // because the compiler is lame. template inline bool operator==(const nsAutoArrayPtr& aLhs, int aRhs) // specifically to allow |smartPtr == 0| { return static_cast(aLhs.get()) == reinterpret_cast(aRhs); } template inline bool operator==(int aLhs, const nsAutoArrayPtr& aRhs) // specifically to allow |0 == smartPtr| { return reinterpret_cast(aLhs) == static_cast(aRhs.get()); } #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) /*****************************************************************************/ // template class nsRefPtrGetterAddRefs; template class nsRefPtr { private: void assign_with_AddRef(T* aRawPtr) { if (aRawPtr) { aRawPtr->AddRef(); } assign_assuming_AddRef(aRawPtr); } void** begin_assignment() { assign_assuming_AddRef(0); return reinterpret_cast(&mRawPtr); } void assign_assuming_AddRef(T* aNewPtr) { T* oldPtr = mRawPtr; mRawPtr = aNewPtr; if (oldPtr) { oldPtr->Release(); } } private: T* mRawPtr; public: typedef T element_type; ~nsRefPtr() { if (mRawPtr) { mRawPtr->Release(); } } // Constructors nsRefPtr() : mRawPtr(0) // default constructor { } nsRefPtr(const nsRefPtr& aSmartPtr) : mRawPtr(aSmartPtr.mRawPtr) // copy-constructor { if (mRawPtr) { mRawPtr->AddRef(); } } nsRefPtr(nsRefPtr&& aRefPtr) : mRawPtr(aRefPtr.mRawPtr) { aRefPtr.mRawPtr = nullptr; } // construct from a raw pointer (of the right type) nsRefPtr(T* aRawPtr) : mRawPtr(aRawPtr) { if (mRawPtr) { mRawPtr->AddRef(); } } template nsRefPtr(already_AddRefed& aSmartPtr) : mRawPtr(aSmartPtr.take()) // construct from |already_AddRefed| { } template nsRefPtr(already_AddRefed&& aSmartPtr) : mRawPtr(aSmartPtr.take()) // construct from |otherRefPtr.forget()| { } nsRefPtr(const nsCOMPtr_helper& aHelper) { void* newRawPtr; if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) { newRawPtr = 0; } mRawPtr = static_cast(newRawPtr); } // Assignment operators nsRefPtr& operator=(const nsRefPtr& aRhs) // copy assignment operator { assign_with_AddRef(aRhs.mRawPtr); return *this; } nsRefPtr& operator=(T* aRhs) // assign from a raw pointer (of the right type) { assign_with_AddRef(aRhs); return *this; } template nsRefPtr& operator=(already_AddRefed& aRhs) // assign from |already_AddRefed| { assign_assuming_AddRef(aRhs.take()); return *this; } template nsRefPtr& operator=(already_AddRefed && aRhs) // assign from |otherRefPtr.forget()| { assign_assuming_AddRef(aRhs.take()); return *this; } nsRefPtr& operator=(const nsCOMPtr_helper& aHelper) { void* newRawPtr; if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) { newRawPtr = 0; } assign_assuming_AddRef(static_cast(newRawPtr)); return *this; } nsRefPtr& operator=(nsRefPtr && aRefPtr) { assign_assuming_AddRef(aRefPtr.mRawPtr); aRefPtr.mRawPtr = nullptr; return *this; } // Other pointer operators void swap(nsRefPtr& aRhs) // ...exchange ownership with |aRhs|; can save a pair of refcount operations { T* temp = aRhs.mRawPtr; aRhs.mRawPtr = mRawPtr; mRawPtr = temp; } void swap(T*& aRhs) // ...exchange ownership with |aRhs|; can save a pair of refcount operations { T* temp = aRhs; aRhs = mRawPtr; mRawPtr = temp; } already_AddRefed forget() // return the value of mRawPtr and null out mRawPtr. Useful for // already_AddRefed return values. { T* temp = 0; swap(temp); return already_AddRefed(temp); } template void forget(I** aRhs) // Set the target of aRhs to the value of mRawPtr and null out mRawPtr. // Useful to avoid unnecessary AddRef/Release pairs with "out" // parameters where aRhs bay be a T** or an I** where I is a base class // of T. { NS_ASSERTION(aRhs, "Null pointer passed to forget!"); *aRhs = mRawPtr; mRawPtr = 0; } T* get() const /* Prefer the implicit conversion provided automatically by |operator T*() const|. Use |get()| to resolve ambiguity or to get a castable pointer. */ { return const_cast(mRawPtr); } operator T*() const /* ...makes an |nsRefPtr| act like its underlying raw pointer type whenever it is used in a context where a raw pointer is expected. It is this operator that makes an |nsRefPtr| substitutable for a raw pointer. Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity. */ { return get(); } T* operator->() const { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->()."); return get(); } // This operator is needed for gcc <= 4.0.* and for Sun Studio; it // causes internal compiler errors for some MSVC versions. (It's not // clear to me whether it should be needed.) #ifndef _MSC_VER template U& operator->*(U V::* aMember) { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator->*()."); return get()->*aMember; } #endif nsRefPtr* get_address() // This is not intended to be used by clients. See |address_of| // below. { return this; } const nsRefPtr* get_address() const // This is not intended to be used by clients. See |address_of| // below. { return this; } public: T& operator*() const { NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsRefPtr with operator*()."); return *get(); } T** StartAssignment() { #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT return reinterpret_cast(begin_assignment()); #else assign_assuming_AddRef(0); return reinterpret_cast(&mRawPtr); #endif } }; template inline void ImplCycleCollectionUnlink(nsRefPtr& aField) { aField = nullptr; } template inline void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, nsRefPtr& aField, const char* aName, uint32_t aFlags = 0) { CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); } template inline nsRefPtr* address_of(nsRefPtr& aPtr) { return aPtr.get_address(); } template inline const nsRefPtr* address_of(const nsRefPtr& aPtr) { return aPtr.get_address(); } template class nsRefPtrGetterAddRefs /* ... This class is designed to be used for anonymous temporary objects in the argument list of calls that return COM interface pointers, e.g., nsRefPtr fooP; ...->GetAddRefedPointer(getter_AddRefs(fooP)) DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. When initialized with a |nsRefPtr|, as in the example above, it returns a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|GetAddRefedPointer| in this case) can fill in. This type should be a nested class inside |nsRefPtr|. */ { public: explicit nsRefPtrGetterAddRefs(nsRefPtr& aSmartPtr) : mTargetSmartPtr(aSmartPtr) { // nothing else to do } operator void**() { return reinterpret_cast(mTargetSmartPtr.StartAssignment()); } operator T**() { return mTargetSmartPtr.StartAssignment(); } T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); } private: nsRefPtr& mTargetSmartPtr; }; template inline nsRefPtrGetterAddRefs getter_AddRefs(nsRefPtr& aSmartPtr) /* Used around a |nsRefPtr| when ...makes the class |nsRefPtrGetterAddRefs| invisible. */ { return nsRefPtrGetterAddRefs(aSmartPtr); } // Comparing two |nsRefPtr|s template inline bool operator==(const nsRefPtr& aLhs, const nsRefPtr& aRhs) { return static_cast(aLhs.get()) == static_cast(aRhs.get()); } template inline bool operator!=(const nsRefPtr& aLhs, const nsRefPtr& aRhs) { return static_cast(aLhs.get()) != static_cast(aRhs.get()); } // Comparing an |nsRefPtr| to a raw pointer template inline bool operator==(const nsRefPtr& aLhs, const U* aRhs) { return static_cast(aLhs.get()) == static_cast(aRhs); } template inline bool operator==(const U* aLhs, const nsRefPtr& aRhs) { return static_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsRefPtr& aLhs, const U* aRhs) { return static_cast(aLhs.get()) != static_cast(aRhs); } template inline bool operator!=(const U* aLhs, const nsRefPtr& aRhs) { return static_cast(aLhs) != static_cast(aRhs.get()); } // To avoid ambiguities caused by the presence of builtin |operator==|s // creating a situation where one of the |operator==| defined above // has a better conversion for one argument and the builtin has a // better conversion for the other argument, define additional // |operator==| without the |const| on the raw pointer. // See bug 65664 for details. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ template inline bool operator==(const nsRefPtr& aLhs, U* aRhs) { return static_cast(aLhs.get()) == const_cast(aRhs); } template inline bool operator==(U* aLhs, const nsRefPtr& aRhs) { return const_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsRefPtr& aLhs, U* aRhs) { return static_cast(aLhs.get()) != const_cast(aRhs); } template inline bool operator!=(U* aLhs, const nsRefPtr& aRhs) { return const_cast(aLhs) != static_cast(aRhs.get()); } #endif // Comparing an |nsRefPtr| to |0| template inline bool operator==(const nsRefPtr& aLhs, NSCAP_Zero* aRhs) // specifically to allow |smartPtr == 0| { return static_cast(aLhs.get()) == reinterpret_cast(aRhs); } template inline bool operator==(NSCAP_Zero* aLhs, const nsRefPtr& aRhs) // specifically to allow |0 == smartPtr| { return reinterpret_cast(aLhs) == static_cast(aRhs.get()); } template inline bool operator!=(const nsRefPtr& aLhs, NSCAP_Zero* aRhs) // specifically to allow |smartPtr != 0| { return static_cast(aLhs.get()) != reinterpret_cast(aRhs); } template inline bool operator!=(NSCAP_Zero* aLhs, const nsRefPtr& aRhs) // specifically to allow |0 != smartPtr| { return reinterpret_cast(aLhs) != static_cast(aRhs.get()); } #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO // We need to explicitly define comparison operators for `int' // because the compiler is lame. template inline bool operator==(const nsRefPtr& aLhs, int aRhs) // specifically to allow |smartPtr == 0| { return static_cast(aLhs.get()) == reinterpret_cast(aRhs); } template inline bool operator==(int aLhs, const nsRefPtr& aRhs) // specifically to allow |0 == smartPtr| { return reinterpret_cast(aLhs) == static_cast(aRhs.get()); } #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) template inline nsresult CallQueryInterface(nsRefPtr& aSourcePtr, DestinationType** aDestPtr) { return CallQueryInterface(aSourcePtr.get(), aDestPtr); } /*****************************************************************************/ template class nsQueryObject : public nsCOMPtr_helper { public: nsQueryObject(T* aRawPtr) : mRawPtr(aRawPtr) { } virtual nsresult NS_FASTCALL operator()(const nsIID& aIID, void** aResult) const { nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult) : NS_ERROR_NULL_POINTER; return status; } private: T* mRawPtr; }; template class nsQueryObjectWithError : public nsCOMPtr_helper { public: nsQueryObjectWithError(T* aRawPtr, nsresult* aErrorPtr) : mRawPtr(aRawPtr), mErrorPtr(aErrorPtr) { } virtual nsresult NS_FASTCALL operator()(const nsIID& aIID, void** aResult) const { nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult) : NS_ERROR_NULL_POINTER; if (mErrorPtr) { *mErrorPtr = status; } return status; } private: T* mRawPtr; nsresult* mErrorPtr; }; template inline nsQueryObject do_QueryObject(T* aRawPtr) { return nsQueryObject(aRawPtr); } template inline nsQueryObject do_QueryObject(nsCOMPtr& aRawPtr) { return nsQueryObject(aRawPtr); } template inline nsQueryObject do_QueryObject(nsRefPtr& aRawPtr) { return nsQueryObject(aRawPtr); } template inline nsQueryObjectWithError do_QueryObject(T* aRawPtr, nsresult* aErrorPtr) { return nsQueryObjectWithError(aRawPtr, aErrorPtr); } template inline nsQueryObjectWithError do_QueryObject(nsCOMPtr& aRawPtr, nsresult* aErrorPtr) { return nsQueryObjectWithError(aRawPtr, aErrorPtr); } template inline nsQueryObjectWithError do_QueryObject(nsRefPtr& aRawPtr, nsresult* aErrorPtr) { return nsQueryObjectWithError(aRawPtr, aErrorPtr); } /*****************************************************************************/ #endif // !defined(nsAutoPtr_h___)