VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/glue/nsCOMPtr.h@ 102324

Last change on this file since 102324 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.6 KB
Line 
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
4 *
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/
9 *
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.
14 *
15 * The Original Code is mozilla.org code.
16 *
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.
21 *
22 * Contributor(s):
23 * Scott Collins <[email protected]> (original author)
24 * L. David Baron <[email protected]>
25 *
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.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40#ifndef nsCOMPtr_h___
41#define nsCOMPtr_h___
42
43/*
44 Having problems?
45
46 See the User Manual at:
47 http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
48
49
50 nsCOMPtr
51 better than a raw pointer
52 for owning objects
53 -- scc
54*/
55
56
57 // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
58#ifndef nsDebug_h___
59#include "nsDebug.h"
60 // for |NS_PRECONDITION|
61#endif
62
63#ifndef nsISupportsUtils_h__
64#include "nsISupportsUtils.h"
65 // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
66#endif
67
68#ifndef nscore_h___
69#include "nscore.h"
70 // for |NS_..._CAST|, |NS_COM|
71#endif
72
73
74/*
75 WARNING:
76 This file defines several macros for internal use only. These macros begin with the
77 prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
78 only for cross-platform compatibility, and are subject to change without notice.
79*/
80
81
82#ifdef _MSC_VER
83 #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
84 // under VC++, we win by inlining StartAssignment
85
86 // Also under VC++, at the highest warning level, we are overwhelmed with warnings
87 // about (unused) inline functions being removed. This is to be expected with
88 // templates, so we disable the warning.
89 #pragma warning( disable: 4514 )
90#endif
91
92#define NSCAP_FEATURE_USE_BASE
93
94#ifdef NS_DEBUG
95 #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
96 #undef NSCAP_FEATURE_USE_BASE
97//#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
98#endif
99
100 /*
101 |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is
102 problematic on a select few of our platforms, e.g., QNX. Therefore, I'm providing
103 a mechanism by which these features can be explicitly disabled from the command-line.
104 */
105
106#ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
107 #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
108#endif
109
110#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
111 // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
112 // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
113 // don't reorder instructions based on aliasing assumptions for
114 // this variable. Fortunately, gcc versions < 3.3 do not do any
115 // optimizations that break nsCOMPtr.
116
117 #define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
118#else
119 #define NS_MAY_ALIAS_PTR(t) t*
120#endif
121
122#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
123 #define NSCAP_FEATURE_USE_BASE
124#endif
125
126
127#ifdef HAVE_CPP_BOOL
128 typedef bool NSCAP_BOOL;
129#else
130 typedef PRBool NSCAP_BOOL;
131#endif
132
133
134
135
136 /*
137 The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
138 allow external clients the ability to add logging or other interesting debug facilities.
139 In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
140 provide (e.g., in "nsTraceRefcnt.h") suitable definitions
141
142 #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
143 #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
144 */
145
146#ifndef NSCAP_ADDREF
147 #define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
148#endif
149
150#ifndef NSCAP_RELEASE
151 #define NSCAP_RELEASE(this, ptr) (ptr)->Release()
152#endif
153
154 // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
155#ifdef NSCAP_LOG_ASSIGNMENT
156 // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
157 // to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
158 // the |nsCOMPtr|.
159 #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
160#else
161 // ...otherwise, just strip it out of the code
162 #define NSCAP_LOG_ASSIGNMENT(this, ptr)
163#endif
164
165#ifndef NSCAP_LOG_RELEASE
166 #define NSCAP_LOG_RELEASE(this, ptr)
167#endif
168
169
170
171
172 /*
173 WARNING:
174 VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
175 in an order that satisfies:
176
177 nsDerivedSafe < nsCOMPtr
178 already_AddRefed < nsCOMPtr
179 nsCOMPtr < nsGetterAddRefs
180
181 The other compilers probably won't complain, so please don't reorder these
182 classes, on pain of breaking 4.2 compatibility.
183 */
184
185
186template <class T>
187class nsDerivedSafe : public T
188 /*
189 No client should ever see or have to type the name of this class. It is the
190 artifact that makes it a compile-time error to call |AddRef| and |Release|
191 on a |nsCOMPtr|. DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
192
193 See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
194
195 This type should be a nested class inside |nsCOMPtr<T>|.
196 */
197 {
198 private:
199#ifdef HAVE_CPP_ACCESS_CHANGING_USING
200 using T::AddRef;
201 using T::Release;
202#else
203 nsrefcnt AddRef(void);
204 nsrefcnt Release(void);
205#endif
206
207#if !defined(AIX) && !defined(IRIX)
208 void operator delete( void*, size_t ); // NOT TO BE IMPLEMENTED
209 // declaring |operator delete| private makes calling delete on an interface pointer a compile error
210#endif
211
212 nsDerivedSafe<T>& operator=( const T& ); // NOT TO BE IMPLEMENTED
213 // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
214
215 /*
216 Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
217 If you see that, that means somebody checked in a [XP]COM interface class that declares an
218 |operator=()|, and that's _bad_. So bad, in fact, that this declaration exists explicitly
219 to stop people from doing it.
220 */
221
222 protected:
223 nsDerivedSafe(); // NOT TO BE IMPLEMENTED
224 /*
225 This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
226 default ctor but inheriting classes without an empty ctor. See bug 209667.
227 */
228 };
229
230#if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
231template <class T>
232nsrefcnt
233nsDerivedSafe<T>::AddRef()
234 {
235 return 0;
236 }
237
238template <class T>
239nsrefcnt
240nsDerivedSafe<T>::Release()
241 {
242 return 0;
243 }
244
245#endif
246
247
248
249template <class T>
250struct already_AddRefed
251 /*
252 ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
253 |AddRef|ing it. You might want to use this as a return type from a function
254 that produces an already |AddRef|ed pointer as a result.
255
256 See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
257
258 This type should be a nested class inside |nsCOMPtr<T>|.
259
260 Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
261 avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
262 case, and perhaps worth the savings in time and space that its specific
263 implementation affords over the more general solution offered by
264 |nsCOMPtr_helper|.
265 */
266 {
267 already_AddRefed( T* aRawPtr )
268 : mRawPtr(aRawPtr)
269 {
270 // nothing else to do here
271 }
272
273 T* get() const { return mRawPtr; }
274
275 T* mRawPtr;
276 };
277
278template <class T>
279inline
280const already_AddRefed<T>
281getter_AddRefs( T* aRawPtr )
282 /*
283 ...makes typing easier, because it deduces the template type, e.g.,
284 you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
285 */
286 {
287 return already_AddRefed<T>(aRawPtr);
288 }
289
290template <class T>
291inline
292const already_AddRefed<T>
293getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
294 {
295 return aAlreadyAddRefedPtr;
296 }
297
298template <class T>
299inline
300const already_AddRefed<T>
301dont_AddRef( T* aRawPtr )
302 {
303 return already_AddRefed<T>(aRawPtr);
304 }
305
306template <class T>
307inline
308const already_AddRefed<T>
309dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
310 {
311 return aAlreadyAddRefedPtr;
312 }
313
314
315
316class nsCOMPtr_helper
317 /*
318 An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
319 that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
320 Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
321
322 Here are the rules for a helper:
323 - it implements |operator()| to produce an interface pointer
324 - (except for its name) |operator()| is a valid [XP]COM `getter'
325 - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
326 - it matches the type requested with the supplied |nsIID| argument
327 - its constructor provides an optional |nsresult*| that |operator()| can fill
328 in with an error when it is executed
329
330 See |class nsGetInterface| for an example.
331 */
332 {
333 public:
334 virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
335 };
336
337/*
338 |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
339 avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
340 is called often enough that the codesize savings are big enough to
341 warrant the specialcasing.
342*/
343
344class NS_COM nsQueryInterface
345 {
346 public:
347 nsQueryInterface( nsISupports* aRawPtr )
348 : mRawPtr(aRawPtr)
349 {
350 // nothing else to do here
351 }
352
353 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
354
355 private:
356 nsISupports* mRawPtr;
357 };
358
359class NS_COM nsQueryInterfaceWithError
360 {
361 public:
362 nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
363 : mRawPtr(aRawPtr),
364 mErrorPtr(error)
365 {
366 // nothing else to do here
367 }
368
369 nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
370
371 private:
372 nsISupports* mRawPtr;
373 nsresult* mErrorPtr;
374 };
375
376inline
377nsQueryInterface
378do_QueryInterface( nsISupports* aRawPtr )
379 {
380 return nsQueryInterface(aRawPtr);
381 }
382
383inline
384nsQueryInterfaceWithError
385do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
386 {
387 return nsQueryInterfaceWithError(aRawPtr, error);
388 }
389
390template <class T>
391inline
392void
393do_QueryInterface( already_AddRefed<T>& )
394 {
395 // This signature exists soley to _stop_ you from doing the bad thing.
396 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
397 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
398 }
399
400template <class T>
401inline
402void
403do_QueryInterface( already_AddRefed<T>&, nsresult* )
404 {
405 // This signature exists soley to _stop_ you from doing the bad thing.
406 // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
407 // someone else is an automatic leak. See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
408 }
409
410
411
412class nsCOMPtr_base
413 /*
414 ...factors implementation for all template versions of |nsCOMPtr|.
415
416 This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
417 because unlike the
418
419 Here's the way people normally do things like this
420
421 template <class T> class Foo { ... };
422 template <> class Foo<void*> { ... };
423 template <class T> class Foo<T*> : private Foo<void*> { ... };
424 */
425 {
426 public:
427
428 nsCOMPtr_base( nsISupports* rawPtr = 0 )
429 : mRawPtr(rawPtr)
430 {
431 // nothing else to do here
432 }
433
434 NS_COM NS_FASTCALL ~nsCOMPtr_base();
435
436 NS_COM void NS_FASTCALL assign_with_AddRef( nsISupports* );
437 NS_COM void NS_FASTCALL assign_from_qi( const nsQueryInterface, const nsIID& );
438 NS_COM void NS_FASTCALL assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
439 NS_COM void NS_FASTCALL assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
440 NS_COM void** NS_FASTCALL begin_assignment();
441
442 protected:
443 NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
444
445 void
446 assign_assuming_AddRef( nsISupports* newPtr )
447 {
448 /*
449 |AddRef()|ing the new value (before entering this function) before
450 |Release()|ing the old lets us safely ignore the self-assignment case.
451 We must, however, be careful only to |Release()| _after_ doing the
452 assignment, in case the |Release()| leads to our _own_ destruction,
453 which would, in turn, cause an incorrect second |Release()| of our old
454 pointer. Thank <[email protected]> for discovering this.
455 */
456 nsISupports* oldPtr = mRawPtr;
457 mRawPtr = newPtr;
458 NSCAP_LOG_ASSIGNMENT(this, newPtr);
459 NSCAP_LOG_RELEASE(this, oldPtr);
460 if ( oldPtr )
461 NSCAP_RELEASE(this, oldPtr);
462 }
463 };
464
465// template <class T> class nsGetterAddRefs;
466
467template <class T>
468class nsCOMPtr
469#ifdef NSCAP_FEATURE_USE_BASE
470 : private nsCOMPtr_base
471#endif
472 {
473
474#ifdef NSCAP_FEATURE_USE_BASE
475 #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
476#else
477 #define NSCAP_CTOR_BASE(x) mRawPtr(x)
478
479 private:
480 void assign_with_AddRef( nsISupports* );
481 void assign_from_qi( const nsQueryInterface, const nsIID& );
482 void assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
483 void assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
484 void** begin_assignment();
485
486 void
487 assign_assuming_AddRef( T* newPtr )
488 {
489 T* oldPtr = mRawPtr;
490 mRawPtr = newPtr;
491 NSCAP_LOG_ASSIGNMENT(this, newPtr);
492 NSCAP_LOG_RELEASE(this, oldPtr);
493 if ( oldPtr )
494 NSCAP_RELEASE(this, oldPtr);
495 }
496
497 private:
498 T* mRawPtr;
499#endif
500
501 public:
502 typedef T element_type;
503
504#ifndef NSCAP_FEATURE_USE_BASE
505 ~nsCOMPtr()
506 {
507 NSCAP_LOG_RELEASE(this, mRawPtr);
508 if ( mRawPtr )
509 NSCAP_RELEASE(this, mRawPtr);
510 }
511#endif
512
513#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
514 void
515 Assert_NoQueryNeeded()
516 {
517 if ( mRawPtr )
518 {
519 nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
520 NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
521 }
522 }
523
524 #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
525#else
526 #define NSCAP_ASSERT_NO_QUERY_NEEDED()
527#endif
528
529
530 // Constructors
531
532 nsCOMPtr()
533 : NSCAP_CTOR_BASE(0)
534 // default constructor
535 {
536 NSCAP_LOG_ASSIGNMENT(this, 0);
537 }
538
539 nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
540 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
541 // copy-constructor
542 {
543 if ( mRawPtr )
544 NSCAP_ADDREF(this, mRawPtr);
545 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
546 }
547
548 nsCOMPtr( T* aRawPtr )
549 : NSCAP_CTOR_BASE(aRawPtr)
550 // construct from a raw pointer (of the right type)
551 {
552 if ( mRawPtr )
553 NSCAP_ADDREF(this, mRawPtr);
554 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
555 NSCAP_ASSERT_NO_QUERY_NEEDED();
556 }
557
558 nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
559 : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
560 // construct from |dont_AddRef(expr)|
561 {
562 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
563 NSCAP_ASSERT_NO_QUERY_NEEDED();
564 }
565
566 nsCOMPtr( const nsQueryInterface qi )
567 : NSCAP_CTOR_BASE(0)
568 // construct from |do_QueryInterface(expr)|
569 {
570 NSCAP_LOG_ASSIGNMENT(this, 0);
571 assign_from_qi(qi, NS_GET_IID(T));
572 }
573
574 nsCOMPtr( const nsQueryInterfaceWithError& qi )
575 : NSCAP_CTOR_BASE(0)
576 // construct from |do_QueryInterface(expr, &rv)|
577 {
578 NSCAP_LOG_ASSIGNMENT(this, 0);
579 assign_from_qi_with_error(qi, NS_GET_IID(T));
580 }
581
582 nsCOMPtr( const nsCOMPtr_helper& helper )
583 : NSCAP_CTOR_BASE(0)
584 // ...and finally, anything else we might need to construct from
585 // can exploit the |nsCOMPtr_helper| facility
586 {
587 NSCAP_LOG_ASSIGNMENT(this, 0);
588 assign_from_helper(helper, NS_GET_IID(T));
589 NSCAP_ASSERT_NO_QUERY_NEEDED();
590 }
591
592
593 // Assignment operators
594
595 nsCOMPtr<T>&
596 operator=( const nsCOMPtr<T>& rhs )
597 // copy assignment operator
598 {
599 assign_with_AddRef(rhs.mRawPtr);
600 return *this;
601 }
602
603 nsCOMPtr<T>&
604 operator=( T* rhs )
605 // assign from a raw pointer (of the right type)
606 {
607 assign_with_AddRef(rhs);
608 NSCAP_ASSERT_NO_QUERY_NEEDED();
609 return *this;
610 }
611
612 nsCOMPtr<T>&
613 operator=( const already_AddRefed<T>& rhs )
614 // assign from |dont_AddRef(expr)|
615 {
616 assign_assuming_AddRef(rhs.mRawPtr);
617 NSCAP_ASSERT_NO_QUERY_NEEDED();
618 return *this;
619 }
620
621 nsCOMPtr<T>&
622 operator=( const nsQueryInterface rhs )
623 // assign from |do_QueryInterface(expr)|
624 {
625 assign_from_qi(rhs, NS_GET_IID(T));
626 return *this;
627 }
628
629 nsCOMPtr<T>&
630 operator=( const nsQueryInterfaceWithError& rhs )
631 // assign from |do_QueryInterface(expr, &rv)|
632 {
633 assign_from_qi_with_error(rhs, NS_GET_IID(T));
634 return *this;
635 }
636
637 nsCOMPtr<T>&
638 operator=( const nsCOMPtr_helper& rhs )
639 // ...and finally, anything else we might need to assign from
640 // can exploit the |nsCOMPtr_helper| facility.
641 {
642 assign_from_helper(rhs, NS_GET_IID(T));
643 NSCAP_ASSERT_NO_QUERY_NEEDED();
644 return *this;
645 }
646
647 void
648 swap( nsCOMPtr<T>& rhs )
649 // ...exchange ownership with |rhs|; can save a pair of refcount operations
650 {
651#ifdef NSCAP_FEATURE_USE_BASE
652 nsISupports* temp = rhs.mRawPtr;
653#else
654 T* temp = rhs.mRawPtr;
655#endif
656 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
657 NSCAP_LOG_ASSIGNMENT(this, temp);
658 NSCAP_LOG_RELEASE(this, mRawPtr);
659 NSCAP_LOG_RELEASE(&rhs, temp);
660 rhs.mRawPtr = mRawPtr;
661 mRawPtr = temp;
662 // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
663 }
664
665 void
666 swap( T*& rhs )
667 // ...exchange ownership with |rhs|; can save a pair of refcount operations
668 {
669#ifdef NSCAP_FEATURE_USE_BASE
670 nsISupports* temp = rhs;
671#else
672 T* temp = rhs;
673#endif
674 NSCAP_LOG_ASSIGNMENT(this, temp);
675 NSCAP_LOG_RELEASE(this, mRawPtr);
676 rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
677 mRawPtr = temp;
678 NSCAP_ASSERT_NO_QUERY_NEEDED();
679 }
680
681
682 // Other pointer operators
683
684 nsDerivedSafe<T>*
685 get() const
686 /*
687 Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
688 Use |get()| _only_ to resolve ambiguity.
689
690 Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
691 */
692 {
693 return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
694 }
695
696 operator nsDerivedSafe<T>*() const
697 /*
698 ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
699 and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
700 that makes an |nsCOMPtr| substitutable for a raw pointer.
701
702 Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
703 */
704 {
705 return get();
706 }
707
708 nsDerivedSafe<T>*
709 operator->() const
710 {
711 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
712 return get();
713 }
714
715#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
716 // broken version for IRIX
717
718 nsCOMPtr<T>*
719 get_address() const
720 // This is not intended to be used by clients. See |address_of|
721 // below.
722 {
723 return NS_CONST_CAST(nsCOMPtr<T>*, this);
724 }
725
726#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
727
728 nsCOMPtr<T>*
729 get_address()
730 // This is not intended to be used by clients. See |address_of|
731 // below.
732 {
733 return this;
734 }
735
736 const nsCOMPtr<T>*
737 get_address() const
738 // This is not intended to be used by clients. See |address_of|
739 // below.
740 {
741 return this;
742 }
743
744#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
745
746 public:
747 nsDerivedSafe<T>&
748 operator*() const
749 {
750 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
751 return *get();
752 }
753
754#if 0
755 private:
756 friend class nsGetterAddRefs<T>;
757#endif
758
759 T**
760 StartAssignment()
761 {
762#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
763 return NS_REINTERPRET_CAST(T**, begin_assignment());
764#else
765 assign_assuming_AddRef(0);
766 return NS_REINTERPRET_CAST(T**, &mRawPtr);
767#endif
768 }
769 };
770
771
772
773 /*
774 Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
775 same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
776 to any valid [XP]COM interface. Otherwise, an |nsCOMPtr<nsISupports>| would only be able
777 to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
778 querying ensues. Clients need to be able to pass around arbitrary interface pointers,
779 without hassles, through intermediary code that doesn't know the exact type.
780 */
781
782NS_SPECIALIZE_TEMPLATE
783class nsCOMPtr<nsISupports>
784 : private nsCOMPtr_base
785 {
786 public:
787 typedef nsISupports element_type;
788
789 // Constructors
790
791 nsCOMPtr()
792 : nsCOMPtr_base(0)
793 // default constructor
794 {
795 NSCAP_LOG_ASSIGNMENT(this, 0);
796 }
797
798 nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
799 : nsCOMPtr_base(aSmartPtr.mRawPtr)
800 // copy constructor
801 {
802 if ( mRawPtr )
803 NSCAP_ADDREF(this, mRawPtr);
804 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
805 }
806
807 nsCOMPtr( nsISupports* aRawPtr )
808 : nsCOMPtr_base(aRawPtr)
809 // construct from a raw pointer (of the right type)
810 {
811 if ( mRawPtr )
812 NSCAP_ADDREF(this, mRawPtr);
813 NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
814 }
815
816 nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
817 : nsCOMPtr_base(aSmartPtr.mRawPtr)
818 // construct from |dont_AddRef(expr)|
819 {
820 NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
821 }
822
823 nsCOMPtr( const nsQueryInterface qi )
824 : nsCOMPtr_base(0)
825 // assign from |do_QueryInterface(expr)|
826 {
827 NSCAP_LOG_ASSIGNMENT(this, 0);
828 assign_from_qi(qi, NS_GET_IID(nsISupports));
829 }
830
831 nsCOMPtr( const nsQueryInterfaceWithError& qi )
832 : nsCOMPtr_base(0)
833 // assign from |do_QueryInterface(expr, &rv)|
834 {
835 NSCAP_LOG_ASSIGNMENT(this, 0);
836 assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
837 }
838
839 nsCOMPtr( const nsCOMPtr_helper& helper )
840 : nsCOMPtr_base(0)
841 // ...and finally, anything else we might need to construct from
842 // can exploit the |nsCOMPtr_helper| facility
843 {
844 NSCAP_LOG_ASSIGNMENT(this, 0);
845 assign_from_helper(helper, NS_GET_IID(nsISupports));
846 }
847
848
849 // Assignment operators
850
851 nsCOMPtr<nsISupports>&
852 operator=( const nsCOMPtr<nsISupports>& rhs )
853 // copy assignment operator
854 {
855 assign_with_AddRef(rhs.mRawPtr);
856 return *this;
857 }
858
859 nsCOMPtr<nsISupports>&
860 operator=( nsISupports* rhs )
861 // assign from a raw pointer (of the right type)
862 {
863 assign_with_AddRef(rhs);
864 return *this;
865 }
866
867 nsCOMPtr<nsISupports>&
868 operator=( const already_AddRefed<nsISupports>& rhs )
869 // assign from |dont_AddRef(expr)|
870 {
871 assign_assuming_AddRef(rhs.mRawPtr);
872 return *this;
873 }
874
875 nsCOMPtr<nsISupports>&
876 operator=( const nsQueryInterface rhs )
877 // assign from |do_QueryInterface(expr)|
878 {
879 assign_from_qi(rhs, NS_GET_IID(nsISupports));
880 return *this;
881 }
882
883 nsCOMPtr<nsISupports>&
884 operator=( const nsQueryInterfaceWithError& rhs )
885 // assign from |do_QueryInterface(expr, &rv)|
886 {
887 assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
888 return *this;
889 }
890
891 nsCOMPtr<nsISupports>&
892 operator=( const nsCOMPtr_helper& rhs )
893 // ...and finally, anything else we might need to assign from
894 // can exploit the |nsCOMPtr_helper| facility.
895 {
896 assign_from_helper(rhs, NS_GET_IID(nsISupports));
897 return *this;
898 }
899
900 void
901 swap( nsCOMPtr<nsISupports>& rhs )
902 // ...exchange ownership with |rhs|; can save a pair of refcount operations
903 {
904 nsISupports* temp = rhs.mRawPtr;
905 NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
906 NSCAP_LOG_ASSIGNMENT(this, temp);
907 NSCAP_LOG_RELEASE(this, mRawPtr);
908 NSCAP_LOG_RELEASE(&rhs, temp);
909 rhs.mRawPtr = mRawPtr;
910 mRawPtr = temp;
911 }
912
913 void
914 swap( nsISupports*& rhs )
915 // ...exchange ownership with |rhs|; can save a pair of refcount operations
916 {
917 nsISupports* temp = rhs;
918 NSCAP_LOG_ASSIGNMENT(this, temp);
919 NSCAP_LOG_RELEASE(this, mRawPtr);
920 rhs = mRawPtr;
921 mRawPtr = temp;
922 }
923
924
925 // Other pointer operators
926
927 nsDerivedSafe<nsISupports>*
928 get() const
929 /*
930 Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
931 Use |get()| _only_ to resolve ambiguity.
932
933 Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
934 */
935 {
936 return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
937 }
938
939 operator nsDerivedSafe<nsISupports>*() const
940 /*
941 ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
942 and |delete|) whenever it is used in a context where a raw pointer is expected. It is this operator
943 that makes an |nsCOMPtr| substitutable for a raw pointer.
944
945 Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
946 */
947 {
948 return get();
949 }
950
951 nsDerivedSafe<nsISupports>*
952 operator->() const
953 {
954 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
955 return get();
956 }
957
958#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
959 // broken version for IRIX
960
961 nsCOMPtr<nsISupports>*
962 get_address() const
963 // This is not intended to be used by clients. See |address_of|
964 // below.
965 {
966 return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
967 }
968
969#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
970
971 nsCOMPtr<nsISupports>*
972 get_address()
973 // This is not intended to be used by clients. See |address_of|
974 // below.
975 {
976 return this;
977 }
978
979 const nsCOMPtr<nsISupports>*
980 get_address() const
981 // This is not intended to be used by clients. See |address_of|
982 // below.
983 {
984 return this;
985 }
986
987#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
988
989 public:
990
991 nsDerivedSafe<nsISupports>&
992 operator*() const
993 {
994 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
995 return *get();
996 }
997
998#if 0
999 private:
1000 friend class nsGetterAddRefs<nsISupports>;
1001#endif
1002
1003 nsISupports**
1004 StartAssignment()
1005 {
1006#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1007 return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
1008#else
1009 assign_assuming_AddRef(0);
1010 return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
1011#endif
1012 }
1013 };
1014
1015#ifndef NSCAP_FEATURE_USE_BASE
1016template <class T>
1017void
1018nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
1019 {
1020 if ( rawPtr )
1021 NSCAP_ADDREF(this, rawPtr);
1022 assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
1023 }
1024
1025template <class T>
1026void
1027nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
1028 {
1029 T* newRawPtr;
1030 if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1031 newRawPtr = 0;
1032 assign_assuming_AddRef(newRawPtr);
1033 }
1034
1035template <class T>
1036void
1037nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
1038 {
1039 T* newRawPtr;
1040 if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1041 newRawPtr = 0;
1042 assign_assuming_AddRef(newRawPtr);
1043 }
1044
1045template <class T>
1046void
1047nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
1048 {
1049 T* newRawPtr;
1050 if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
1051 newRawPtr = 0;
1052 assign_assuming_AddRef(newRawPtr);
1053 }
1054
1055template <class T>
1056void**
1057nsCOMPtr<T>::begin_assignment()
1058 {
1059 assign_assuming_AddRef(0);
1060 return NS_REINTERPRET_CAST(void**, &mRawPtr);
1061 }
1062#endif
1063
1064#ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
1065
1066// This is the broken version for IRIX, which can't handle the version below.
1067
1068template <class T>
1069inline
1070nsCOMPtr<T>*
1071address_of( const nsCOMPtr<T>& aPtr )
1072 {
1073 return aPtr.get_address();
1074 }
1075
1076#else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1077
1078template <class T>
1079inline
1080nsCOMPtr<T>*
1081address_of( nsCOMPtr<T>& aPtr )
1082 {
1083 return aPtr.get_address();
1084 }
1085
1086template <class T>
1087inline
1088const nsCOMPtr<T>*
1089address_of( const nsCOMPtr<T>& aPtr )
1090 {
1091 return aPtr.get_address();
1092 }
1093
1094#endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
1095
1096template <class T>
1097class nsGetterAddRefs
1098 /*
1099 ...
1100
1101 This class is designed to be used for anonymous temporary objects in the
1102 argument list of calls that return COM interface pointers, e.g.,
1103
1104 nsCOMPtr<IFoo> fooP;
1105 ...->QueryInterface(iid, getter_AddRefs(fooP))
1106
1107 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1108
1109 When initialized with a |nsCOMPtr|, as in the example above, it returns
1110 a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
1111 case) can fill in.
1112
1113 This type should be a nested class inside |nsCOMPtr<T>|.
1114 */
1115 {
1116 public:
1117 explicit
1118 nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
1119 : mTargetSmartPtr(aSmartPtr)
1120 {
1121 // nothing else to do
1122 }
1123
1124#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
1125 ~nsGetterAddRefs()
1126 {
1127#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1128 NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1129#endif
1130
1131#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
1132 mTargetSmartPtr.Assert_NoQueryNeeded();
1133#endif
1134 }
1135#endif
1136
1137 operator void**()
1138 {
1139 return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
1140 }
1141
1142 operator nsISupports**()
1143 {
1144 return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
1145 }
1146
1147 operator T**()
1148 {
1149 return mTargetSmartPtr.StartAssignment();
1150 }
1151
1152 T*&
1153 operator*()
1154 {
1155 return *(mTargetSmartPtr.StartAssignment());
1156 }
1157
1158 private:
1159 nsCOMPtr<T>& mTargetSmartPtr;
1160 };
1161
1162
1163NS_SPECIALIZE_TEMPLATE
1164class nsGetterAddRefs<nsISupports>
1165 {
1166 public:
1167 explicit
1168 nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
1169 : mTargetSmartPtr(aSmartPtr)
1170 {
1171 // nothing else to do
1172 }
1173
1174#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
1175 ~nsGetterAddRefs()
1176 {
1177 NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
1178 }
1179#endif
1180
1181 operator void**()
1182 {
1183 return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
1184 }
1185
1186 operator nsISupports**()
1187 {
1188 return mTargetSmartPtr.StartAssignment();
1189 }
1190
1191 nsISupports*&
1192 operator*()
1193 {
1194 return *(mTargetSmartPtr.StartAssignment());
1195 }
1196
1197 private:
1198 nsCOMPtr<nsISupports>& mTargetSmartPtr;
1199 };
1200
1201
1202template <class T>
1203inline
1204nsGetterAddRefs<T>
1205getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
1206 /*
1207 Used around a |nsCOMPtr| when
1208 ...makes the class |nsGetterAddRefs<T>| invisible.
1209 */
1210 {
1211 return nsGetterAddRefs<T>(aSmartPtr);
1212 }
1213
1214
1215
1216 // Comparing two |nsCOMPtr|s
1217
1218template <class T, class U>
1219inline
1220NSCAP_BOOL
1221operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1222 {
1223 return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
1224 }
1225
1226
1227template <class T, class U>
1228inline
1229NSCAP_BOOL
1230operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
1231 {
1232 return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
1233 }
1234
1235
1236 // Comparing an |nsCOMPtr| to a raw pointer
1237
1238template <class T, class U>
1239inline
1240NSCAP_BOOL
1241operator==( const nsCOMPtr<T>& lhs, const U* rhs )
1242 {
1243 return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
1244 }
1245
1246template <class T, class U>
1247inline
1248NSCAP_BOOL
1249operator==( const U* lhs, const nsCOMPtr<T>& rhs )
1250 {
1251 return lhs == NS_STATIC_CAST(const T*, rhs.get());
1252 }
1253
1254template <class T, class U>
1255inline
1256NSCAP_BOOL
1257operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
1258 {
1259 return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
1260 }
1261
1262template <class T, class U>
1263inline
1264NSCAP_BOOL
1265operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
1266 {
1267 return lhs != NS_STATIC_CAST(const T*, rhs.get());
1268 }
1269
1270 // To avoid ambiguities caused by the presence of builtin |operator==|s
1271 // creating a situation where one of the |operator==| defined above
1272 // has a better conversion for one argument and the builtin has a
1273 // better conversion for the other argument, define additional
1274 // |operator==| without the |const| on the raw pointer.
1275 // See bug 65664 for details.
1276
1277// This is defined by an autoconf test, but VC++ also has a bug that
1278// prevents us from using these. (It also, fortunately, has the bug
1279// that we don't need them either.)
1280#if defined(_MSC_VER) && (_MSC_VER < 1310)
1281#define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1282#endif
1283
1284#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
1285template <class T, class U>
1286inline
1287NSCAP_BOOL
1288operator==( const nsCOMPtr<T>& lhs, U* rhs )
1289 {
1290 return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
1291 }
1292
1293template <class T, class U>
1294inline
1295NSCAP_BOOL
1296operator==( U* lhs, const nsCOMPtr<T>& rhs )
1297 {
1298 return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
1299 }
1300
1301template <class T, class U>
1302inline
1303NSCAP_BOOL
1304operator!=( const nsCOMPtr<T>& lhs, U* rhs )
1305 {
1306 return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
1307 }
1308
1309template <class T, class U>
1310inline
1311NSCAP_BOOL
1312operator!=( U* lhs, const nsCOMPtr<T>& rhs )
1313 {
1314 return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
1315 }
1316#endif
1317
1318
1319
1320 // Comparing an |nsCOMPtr| to |0|
1321
1322class NSCAP_Zero;
1323
1324template <class T>
1325inline
1326NSCAP_BOOL
1327operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1328 // specifically to allow |smartPtr == 0|
1329 {
1330 return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
1331 }
1332
1333template <class T>
1334inline
1335NSCAP_BOOL
1336operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1337 // specifically to allow |0 == smartPtr|
1338 {
1339 return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
1340 }
1341
1342template <class T>
1343inline
1344NSCAP_BOOL
1345operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
1346 // specifically to allow |smartPtr != 0|
1347 {
1348 return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
1349 }
1350
1351template <class T>
1352inline
1353NSCAP_BOOL
1354operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
1355 // specifically to allow |0 != smartPtr|
1356 {
1357 return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
1358 }
1359
1360
1361#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1362
1363 // We need to explicitly define comparison operators for `int'
1364 // because the compiler is lame.
1365
1366template <class T>
1367inline
1368NSCAP_BOOL
1369operator==( const nsCOMPtr<T>& lhs, int rhs )
1370 // specifically to allow |smartPtr == 0|
1371 {
1372 return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
1373 }
1374
1375template <class T>
1376inline
1377NSCAP_BOOL
1378operator==( int lhs, const nsCOMPtr<T>& rhs )
1379 // specifically to allow |0 == smartPtr|
1380 {
1381 return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
1382 }
1383
1384#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1385
1386 // Comparing any two [XP]COM objects for identity
1387
1388inline
1389NSCAP_BOOL
1390SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
1391 {
1392 return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
1393 }
1394
1395
1396
1397template <class SourceType, class DestinationType>
1398inline
1399nsresult
1400CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
1401 {
1402 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1403 }
1404
1405#endif // !defined(nsCOMPtr_h___)
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette