Bug 1494765 - Allow assignment from an nsCOMPtr of a related type r=froydnj
☠☠ backed out by 825f10de7839 ☠ ☠
authorAndrew McCreight <continuation@gmail.com>
Mon, 01 Oct 2018 20:50:32 +0000
changeset 494799 cb01170872de75622282968dbc8bccaab391be0d
parent 494798 8fb46c61e091b2b812ebeee76466abb520cf4f85
child 494800 825f10de78392d7f9578b7950b498cfc280ddcf5
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1494765
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1494765 - Allow assignment from an nsCOMPtr of a related type r=froydnj This adds support for conversion from nsCOMPtr<A> to nsCOMPtr<B> when A is a subclass of B. There's no reason to not allow this, and RefPtr already supports this. Differential Revision: https://phabricator.services.mozilla.com/D7226
xpcom/base/nsCOMPtr.h
--- a/xpcom/base/nsCOMPtr.h
+++ b/xpcom/base/nsCOMPtr.h
@@ -464,25 +464,51 @@ public:
   {
     assert_validity();
     if (mRawPtr) {
       NSCAP_ADDREF(this, mRawPtr);
     }
     NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
   }
 
+  template <class U>
+  MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr<U>& aSmartPtr)
+    : NSCAP_CTOR_BASE(aSmartPtr.get())
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assert_validity();
+    if (mRawPtr) {
+      NSCAP_ADDREF(this, mRawPtr);
+    }
+    NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.get());
+  }
+
   nsCOMPtr(nsCOMPtr<T>&& aSmartPtr)
     : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
   {
     assert_validity();
     aSmartPtr.mRawPtr = nullptr;
     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     NSCAP_ASSERT_NO_QUERY_NEEDED();
   }
 
+  template <class U>
+  nsCOMPtr(nsCOMPtr<U>&& aSmartPtr)
+    : NSCAP_CTOR_BASE(aSmartPtr.forget().template downcast<T>().take())
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assert_validity();
+    NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
+    NSCAP_ASSERT_NO_QUERY_NEEDED();
+  }
+
   MOZ_IMPLICIT nsCOMPtr(T* aRawPtr)
     : NSCAP_CTOR_BASE(aRawPtr)
   {
     assert_validity();
     if (mRawPtr) {
       NSCAP_ADDREF(this, mRawPtr);
     }
     NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
@@ -614,23 +640,44 @@ public:
   // Assignment operators
 
   nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs)
   {
     assign_with_AddRef(aRhs.mRawPtr);
     return *this;
   }
 
+  template<class U>
+  nsCOMPtr<T>& operator=(const nsCOMPtr<U>& aRhs)
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assign_with_AddRef(static_cast<T*>(aRhs.get()));
+    return *this;
+  }
+
   nsCOMPtr<T>& operator=(nsCOMPtr<T>&& aRhs)
   {
     assign_assuming_AddRef(aRhs.forget().take());
     NSCAP_ASSERT_NO_QUERY_NEEDED();
     return *this;
   }
 
+  template<class U>
+  nsCOMPtr<T>& operator=(nsCOMPtr<U>&& aRhs)
+  {
+    // Make sure that U actually inherits from T
+    static_assert(mozilla::IsBaseOf<T, U>::value,
+                  "U should be a subclass of T");
+    assign_assuming_AddRef(aRhs.forget().template downcast<T>().take());
+    NSCAP_ASSERT_NO_QUERY_NEEDED();
+    return *this;
+  }
+
   nsCOMPtr<T>& operator=(T* aRhs)
   {
     assign_with_AddRef(aRhs);
     NSCAP_ASSERT_NO_QUERY_NEEDED();
     return *this;
   }
 
   nsCOMPtr<T>& operator=(decltype(nullptr))