tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RefPtr.h (17965B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_RefPtr_h
      8 #define mozilla_RefPtr_h
      9 
     10 #include "mozilla/AlreadyAddRefed.h"
     11 #include "mozilla/Assertions.h"
     12 #include "mozilla/Attributes.h"
     13 #include "mozilla/DbgMacro.h"
     14 
     15 #include <type_traits>
     16 
     17 /*****************************************************************************/
     18 
     19 // template <class T> class RefPtrGetterAddRefs;
     20 
     21 class nsQueryReferent;
     22 class nsCOMPtr_helper;
     23 class nsISupports;
     24 
     25 namespace mozilla {
     26 template <class T>
     27 class MovingNotNull;
     28 template <class T>
     29 class NotNull;
     30 template <class T>
     31 class OwningNonNull;
     32 template <class T>
     33 class StaticLocalRefPtr;
     34 template <class T>
     35 class StaticRefPtr;
     36 
     37 // Traditionally, RefPtr supports automatic refcounting of any pointer type
     38 // with AddRef() and Release() methods that follow the traditional semantics.
     39 //
     40 // This traits class can be specialized to operate on other pointer types. For
     41 // example, we specialize this trait for opaque FFI types that represent
     42 // refcounted objects in Rust.
     43 //
     44 // Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
     45 // qualified type.
     46 template <class U>
     47 struct RefPtrTraits {
     48  static void AddRef(U* aPtr) { aPtr->AddRef(); }
     49  static void Release(U* aPtr) { aPtr->Release(); }
     50 };
     51 
     52 }  // namespace mozilla
     53 
     54 template <class T>
     55 class MOZ_IS_REFPTR RefPtr {
     56 private:
     57  void assign_with_AddRef(T* aRawPtr) {
     58    if (aRawPtr) {
     59      ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
     60    }
     61    assign_assuming_AddRef(aRawPtr);
     62  }
     63 
     64  void assign_assuming_AddRef(T* aNewPtr) {
     65    T* oldPtr = mRawPtr;
     66    mRawPtr = aNewPtr;
     67    if (oldPtr) {
     68      ConstRemovingRefPtrTraits<T>::Release(oldPtr);
     69    }
     70  }
     71 
     72 private:
     73  T* MOZ_OWNING_REF mRawPtr;
     74 
     75 public:
     76  typedef T element_type;
     77 
     78  ~RefPtr() {
     79    if (mRawPtr) {
     80      ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
     81    }
     82  }
     83 
     84  // Constructors
     85 
     86  constexpr RefPtr()
     87      : mRawPtr(nullptr)
     88  // default constructor
     89  {}
     90 
     91  RefPtr(const RefPtr<T>& aSmartPtr)
     92      : mRawPtr(aSmartPtr.mRawPtr)
     93  // copy-constructor
     94  {
     95    if (mRawPtr) {
     96      ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
     97    }
     98  }
     99 
    100  RefPtr(RefPtr<T>&& aRefPtr) noexcept : mRawPtr(aRefPtr.mRawPtr) {
    101    aRefPtr.mRawPtr = nullptr;
    102  }
    103 
    104  // construct from a raw pointer (of the right type)
    105 
    106  MOZ_IMPLICIT RefPtr(T* aRawPtr) : mRawPtr(aRawPtr) {
    107    if (mRawPtr) {
    108      ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
    109    }
    110  }
    111 
    112  MOZ_IMPLICIT constexpr RefPtr(std::nullptr_t) : mRawPtr(nullptr) {}
    113 
    114  template <typename I,
    115            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
    116  MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
    117      : mRawPtr(aSmartPtr.take())
    118  // construct from |already_AddRefed|
    119  {}
    120 
    121  template <typename I,
    122            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
    123  MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr)
    124      : mRawPtr(aSmartPtr.take())
    125  // construct from |otherRefPtr.forget()|
    126  {}
    127 
    128  template <typename I,
    129            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
    130  MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr)
    131      : mRawPtr(aSmartPtr.get())
    132  // copy-construct from a smart pointer with a related pointer type
    133  {
    134    if (mRawPtr) {
    135      ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
    136    }
    137  }
    138 
    139  template <typename I,
    140            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
    141  MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr)
    142      : mRawPtr(aSmartPtr.forget().take())
    143  // construct from |Move(RefPtr<SomeSubclassOfT>)|.
    144  {}
    145 
    146  template <typename I,
    147            typename = std::enable_if_t<!std::is_same_v<I, RefPtr<T>> &&
    148                                        std::is_convertible_v<I, RefPtr<T>>>>
    149  MOZ_IMPLICIT RefPtr(const mozilla::NotNull<I>& aSmartPtr)
    150      : mRawPtr(RefPtr<T>(aSmartPtr.get()).forget().take())
    151  // construct from |mozilla::NotNull|.
    152  {}
    153 
    154  template <typename I,
    155            typename = std::enable_if_t<!std::is_same_v<I, RefPtr<T>> &&
    156                                        std::is_convertible_v<I, RefPtr<T>>>>
    157  MOZ_IMPLICIT RefPtr(mozilla::MovingNotNull<I>&& aSmartPtr)
    158      : mRawPtr(RefPtr<T>(std::move(aSmartPtr).unwrapBasePtr()).forget().take())
    159  // construct from |mozilla::MovingNotNull|.
    160  {}
    161 
    162  MOZ_IMPLICIT RefPtr(const nsQueryReferent& aHelper);
    163  MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
    164 
    165  // Defined in OwningNonNull.h
    166  template <class U>
    167  MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
    168 
    169  // Defined in StaticLocalPtr.h
    170  template <class U>
    171  MOZ_IMPLICIT RefPtr(const mozilla::StaticLocalRefPtr<U>& aOther);
    172 
    173  // Defined in StaticPtr.h
    174  template <class U>
    175  MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
    176 
    177  // Assignment operators
    178 
    179  RefPtr<T>& operator=(decltype(nullptr)) {
    180    assign_assuming_AddRef(nullptr);
    181    return *this;
    182  }
    183 
    184  RefPtr<T>& operator=(const RefPtr<T>& aRhs)
    185  // copy assignment operator
    186  {
    187    assign_with_AddRef(aRhs.mRawPtr);
    188    return *this;
    189  }
    190 
    191  template <typename I>
    192  RefPtr<T>& operator=(const RefPtr<I>& aRhs)
    193  // assign from an RefPtr of a related pointer type
    194  {
    195    assign_with_AddRef(aRhs.get());
    196    return *this;
    197  }
    198 
    199  RefPtr<T>& operator=(T* aRhs)
    200  // assign from a raw pointer (of the right type)
    201  {
    202    assign_with_AddRef(aRhs);
    203    return *this;
    204  }
    205 
    206  template <typename I>
    207  RefPtr<T>& operator=(already_AddRefed<I>& aRhs)
    208  // assign from |already_AddRefed|
    209  {
    210    assign_assuming_AddRef(aRhs.take());
    211    return *this;
    212  }
    213 
    214  template <typename I>
    215  RefPtr<T>& operator=(already_AddRefed<I>&& aRhs)
    216  // assign from |otherRefPtr.forget()|
    217  {
    218    assign_assuming_AddRef(aRhs.take());
    219    return *this;
    220  }
    221 
    222  RefPtr<T>& operator=(const nsQueryReferent& aQueryReferent);
    223  RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
    224 
    225  template <typename I,
    226            typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
    227  RefPtr<T>& operator=(RefPtr<I>&& aRefPtr) noexcept {
    228    assign_assuming_AddRef(aRefPtr.forget().take());
    229    return *this;
    230  }
    231 
    232  template <typename I,
    233            typename = std::enable_if_t<std::is_convertible_v<I, RefPtr<T>>>>
    234  RefPtr<T>& operator=(const mozilla::NotNull<I>& aSmartPtr)
    235  // assign from |mozilla::NotNull|.
    236  {
    237    assign_assuming_AddRef(RefPtr<T>(aSmartPtr.get()).forget().take());
    238    return *this;
    239  }
    240 
    241  template <typename I,
    242            typename = std::enable_if_t<std::is_convertible_v<I, RefPtr<T>>>>
    243  RefPtr<T>& operator=(mozilla::MovingNotNull<I>&& aSmartPtr)
    244  // assign from |mozilla::MovingNotNull|.
    245  {
    246    assign_assuming_AddRef(
    247        RefPtr<T>(std::move(aSmartPtr).unwrapBasePtr()).forget().take());
    248    return *this;
    249  }
    250 
    251  // Defined in OwningNonNull.h
    252  template <class U>
    253  RefPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther);
    254 
    255  // Defined in StaticLocalPtr.h
    256  template <class U>
    257  RefPtr<T>& operator=(const mozilla::StaticLocalRefPtr<U>& aOther);
    258 
    259  // Defined in StaticPtr.h
    260  template <class U>
    261  RefPtr<T>& operator=(const mozilla::StaticRefPtr<U>& aOther);
    262 
    263  // Other pointer operators
    264 
    265  void swap(RefPtr<T>& aRhs)
    266  // ...exchange ownership with |aRhs|; can save a pair of refcount operations
    267  {
    268    T* temp = aRhs.mRawPtr;
    269    aRhs.mRawPtr = mRawPtr;
    270    mRawPtr = temp;
    271  }
    272 
    273  void swap(T*& aRhs)
    274  // ...exchange ownership with |aRhs|; can save a pair of refcount operations
    275  {
    276    T* temp = aRhs;
    277    aRhs = mRawPtr;
    278    mRawPtr = temp;
    279  }
    280 
    281  already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
    282  // return the value of mRawPtr and null out mRawPtr. Useful for
    283  // already_AddRefed return values.
    284  {
    285    T* temp = nullptr;
    286    swap(temp);
    287    return already_AddRefed<T>(temp);
    288  }
    289 
    290  template <typename I>
    291  void forget(I** aRhs)
    292  // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
    293  // Useful to avoid unnecessary AddRef/Release pairs with "out"
    294  // parameters where aRhs bay be a T** or an I** where I is a base class
    295  // of T.
    296  {
    297    MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
    298    *aRhs = mRawPtr;
    299    mRawPtr = nullptr;
    300  }
    301 
    302  void forget(nsISupports** aRhs) {
    303    MOZ_ASSERT(aRhs, "Null pointer passed to forget!");
    304    *aRhs = ToSupports(mRawPtr);
    305    mRawPtr = nullptr;
    306  }
    307 
    308  T* get() const
    309  /*
    310    Prefer the implicit conversion provided automatically by |operator T*()
    311    const|. Use |get()| to resolve ambiguity or to get a castable pointer.
    312  */
    313  {
    314    return const_cast<T*>(mRawPtr);
    315  }
    316 
    317  operator T*() const&
    318  /*
    319    ...makes an |RefPtr| act like its underlying raw pointer type whenever it
    320    is used in a context where a raw pointer is expected.  It is this operator
    321    that makes an |RefPtr| substitutable for a raw pointer.
    322 
    323    Prefer the implicit use of this operator to calling |get()|, except where
    324    necessary to resolve ambiguity.
    325  */
    326  {
    327    return get();
    328  }
    329 
    330  // Don't allow implicit conversion of temporary RefPtr to raw pointer,
    331  // because the refcount might be one and the pointer will immediately become
    332  // invalid.
    333  operator T*() const&& = delete;
    334 
    335  // These are needed to avoid the deleted operator above.  XXX Why is operator!
    336  // needed separately?  Shouldn't the compiler prefer using the non-deleted
    337  // operator bool instead of the deleted operator T*?
    338  explicit operator bool() const { return !!mRawPtr; }
    339  bool operator!() const { return !mRawPtr; }
    340 
    341  T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
    342    MOZ_ASSERT(mRawPtr != nullptr,
    343               "You can't dereference a NULL RefPtr with operator->().");
    344    return get();
    345  }
    346 
    347  template <typename R, typename... Args>
    348  class Proxy {
    349    typedef R (T::*member_function)(Args...);
    350    T* mRawPtr;
    351    member_function mFunction;
    352 
    353   public:
    354    Proxy(T* aRawPtr, member_function aFunction)
    355        : mRawPtr(aRawPtr), mFunction(aFunction) {}
    356    template <typename... ActualArgs>
    357    R operator()(ActualArgs&&... aArgs) {
    358      return ((*mRawPtr).*mFunction)(std::forward<ActualArgs>(aArgs)...);
    359    }
    360  };
    361 
    362  template <typename R, typename... Args>
    363  Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const {
    364    MOZ_ASSERT(mRawPtr != nullptr,
    365               "You can't dereference a NULL RefPtr with operator->*().");
    366    return Proxy<R, Args...>(get(), aFptr);
    367  }
    368 
    369  RefPtr<T>* get_address()
    370  // This is not intended to be used by clients.  See |address_of|
    371  // below.
    372  {
    373    return this;
    374  }
    375 
    376  const RefPtr<T>* get_address() const
    377  // This is not intended to be used by clients.  See |address_of|
    378  // below.
    379  {
    380    return this;
    381  }
    382 
    383 public:
    384  T& operator*() const {
    385    MOZ_ASSERT(mRawPtr != nullptr,
    386               "You can't dereference a NULL RefPtr with operator*().");
    387    return *get();
    388  }
    389 
    390  T** StartAssignment() {
    391    assign_assuming_AddRef(nullptr);
    392    return reinterpret_cast<T**>(&mRawPtr);
    393  }
    394 
    395 private:
    396  // This helper class makes |RefPtr<const T>| possible by casting away
    397  // the constness from the pointer when calling AddRef() and Release().
    398  //
    399  // This is necessary because AddRef() and Release() implementations can't
    400  // generally expected to be const themselves (without heavy use of |mutable|
    401  // and |const_cast| in their own implementations).
    402  //
    403  // This should be sound because while |RefPtr<const T>| provides a
    404  // const view of an object, the object itself should not be const (it
    405  // would have to be allocated as |new const T| or similar to be const).
    406  template <class U>
    407  struct ConstRemovingRefPtrTraits {
    408    static void AddRef(U* aPtr) { mozilla::RefPtrTraits<U>::AddRef(aPtr); }
    409    static void Release(U* aPtr) { mozilla::RefPtrTraits<U>::Release(aPtr); }
    410  };
    411  template <class U>
    412  struct ConstRemovingRefPtrTraits<const U> {
    413    static void AddRef(const U* aPtr) {
    414      mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
    415    }
    416    static void Release(const U* aPtr) {
    417      mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
    418    }
    419  };
    420 };
    421 
    422 class nsCycleCollectionTraversalCallback;
    423 template <typename T>
    424 void CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback,
    425                              T* aChild, const char* aName, uint32_t aFlags);
    426 
    427 template <typename T>
    428 inline void ImplCycleCollectionUnlink(RefPtr<T>& aField) {
    429  aField = nullptr;
    430 }
    431 
    432 template <typename T>
    433 inline void ImplCycleCollectionTraverse(
    434    nsCycleCollectionTraversalCallback& aCallback, const RefPtr<T>& aField,
    435    const char* aName, uint32_t aFlags = 0) {
    436  CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
    437 }
    438 
    439 template <class T>
    440 inline RefPtr<T>* address_of(RefPtr<T>& aPtr) {
    441  return aPtr.get_address();
    442 }
    443 
    444 template <class T>
    445 inline const RefPtr<T>* address_of(const RefPtr<T>& aPtr) {
    446  return aPtr.get_address();
    447 }
    448 
    449 template <class T>
    450 class RefPtrGetterAddRefs
    451 /*
    452  ...
    453 
    454  This class is designed to be used for anonymous temporary objects in the
    455  argument list of calls that return COM interface pointers, e.g.,
    456 
    457    RefPtr<IFoo> fooP;
    458    ...->GetAddRefedPointer(getter_AddRefs(fooP))
    459 
    460  DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
    461 
    462  When initialized with a |RefPtr|, as in the example above, it returns
    463  a |void**|, a |T**|, or an |nsISupports**| as needed, that the
    464  outer call (|GetAddRefedPointer| in this case) can fill in.
    465 
    466  This type should be a nested class inside |RefPtr<T>|.
    467 */
    468 {
    469 public:
    470  explicit RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr)
    471      : mTargetSmartPtr(aSmartPtr) {
    472    // nothing else to do
    473  }
    474 
    475  operator void**() {
    476    return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
    477  }
    478 
    479  operator T**() { return mTargetSmartPtr.StartAssignment(); }
    480 
    481  T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
    482 
    483 private:
    484  RefPtr<T>& mTargetSmartPtr;
    485 };
    486 
    487 template <class T>
    488 inline RefPtrGetterAddRefs<T> getter_AddRefs(RefPtr<T>& aSmartPtr)
    489 /*
    490  Used around a |RefPtr| when
    491  ...makes the class |RefPtrGetterAddRefs<T>| invisible.
    492 */
    493 {
    494  return RefPtrGetterAddRefs<T>(aSmartPtr);
    495 }
    496 
    497 // Comparing two |RefPtr|s
    498 
    499 template <class T, class U>
    500 inline bool operator==(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) {
    501  return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
    502 }
    503 
    504 template <class T, class U>
    505 inline bool operator!=(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) {
    506  return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
    507 }
    508 
    509 // Comparing an |RefPtr| to a raw pointer
    510 
    511 template <class T, class U>
    512 inline bool operator==(const RefPtr<T>& aLhs, const U* aRhs) {
    513  return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
    514 }
    515 
    516 template <class T, class U>
    517 inline bool operator==(const U* aLhs, const RefPtr<T>& aRhs) {
    518  return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
    519 }
    520 
    521 template <class T, class U>
    522 inline bool operator!=(const RefPtr<T>& aLhs, const U* aRhs) {
    523  return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
    524 }
    525 
    526 template <class T, class U>
    527 inline bool operator!=(const U* aLhs, const RefPtr<T>& aRhs) {
    528  return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
    529 }
    530 
    531 template <class T, class U>
    532 inline bool operator==(const RefPtr<T>& aLhs, U* aRhs) {
    533  return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
    534 }
    535 
    536 template <class T, class U>
    537 inline bool operator==(U* aLhs, const RefPtr<T>& aRhs) {
    538  return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
    539 }
    540 
    541 template <class T, class U>
    542 inline bool operator!=(const RefPtr<T>& aLhs, U* aRhs) {
    543  return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
    544 }
    545 
    546 template <class T, class U>
    547 inline bool operator!=(U* aLhs, const RefPtr<T>& aRhs) {
    548  return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
    549 }
    550 
    551 // Comparing an |RefPtr| to |nullptr|
    552 
    553 template <class T>
    554 inline bool operator==(const RefPtr<T>& aLhs, decltype(nullptr)) {
    555  return aLhs.get() == nullptr;
    556 }
    557 
    558 template <class T>
    559 inline bool operator==(decltype(nullptr), const RefPtr<T>& aRhs) {
    560  return nullptr == aRhs.get();
    561 }
    562 
    563 template <class T>
    564 inline bool operator!=(const RefPtr<T>& aLhs, decltype(nullptr)) {
    565  return aLhs.get() != nullptr;
    566 }
    567 
    568 template <class T>
    569 inline bool operator!=(decltype(nullptr), const RefPtr<T>& aRhs) {
    570  return nullptr != aRhs.get();
    571 }
    572 
    573 // MOZ_DBG support
    574 
    575 template <class T>
    576 std::ostream& operator<<(std::ostream& aOut, const RefPtr<T>& aObj) {
    577  return mozilla::DebugValue(aOut, aObj.get());
    578 }
    579 
    580 /*****************************************************************************/
    581 
    582 template <class T>
    583 inline already_AddRefed<T> do_AddRef(T* aObj) {
    584  RefPtr<T> ref(aObj);
    585  return ref.forget();
    586 }
    587 
    588 template <class T>
    589 inline already_AddRefed<T> do_AddRef(const RefPtr<T>& aObj) {
    590  RefPtr<T> ref(aObj);
    591  return ref.forget();
    592 }
    593 
    594 namespace mozilla {
    595 
    596 /**
    597 * Helper function to be able to conveniently write things like:
    598 *
    599 *   already_AddRefed<T>
    600 *   f(...)
    601 *   {
    602 *     return MakeAndAddRef<T>(...);
    603 *   }
    604 */
    605 template <typename T, typename... Args>
    606 already_AddRefed<T> MakeAndAddRef(Args&&... aArgs) {
    607  RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
    608  return p.forget();
    609 }
    610 
    611 /**
    612 * Helper function to be able to conveniently write things like:
    613 *
    614 *   auto runnable =
    615 * MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
    616 *       mOnSuccess, mOnFailure, *error, mWindowID);
    617 */
    618 template <typename T, typename... Args>
    619 RefPtr<T> MakeRefPtr(Args&&... aArgs) {
    620  RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
    621  return p;
    622 }
    623 
    624 }  // namespace mozilla
    625 
    626 /**
    627 * Deduction guide to allow simple `RefPtr` definitions from an
    628 * already_AddRefed<T> without repeating the type, e.g.:
    629 *
    630 *   RefPtr ptr = MakeAndAddRef<SomeType>(...);
    631 */
    632 template <typename T>
    633 RefPtr(already_AddRefed<T>) -> RefPtr<T>;
    634 
    635 #endif /* mozilla_RefPtr_h */