Bug 1255857 - Allow mozilla::UniquePtr's deleter template argument to customize the pointer type; r=froydnj
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 11 Mar 2016 14:48:58 -0500
changeset 288353 256bbc9c278e0891f66466038f3c0902cfb48da8
parent 288352 631c9549411d4cc9cc927036df0f9b3b3be596c3
child 288354 5c9c719705b1cdf7dd0cb9ec142e15764551f093
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1255857
milestone48.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 1255857 - Allow mozilla::UniquePtr's deleter template argument to customize the pointer type; r=froydnj
mfbt/UniquePtr.h
mfbt/tests/TestUniquePtr.cpp
--- a/mfbt/UniquePtr.h
+++ b/mfbt/UniquePtr.h
@@ -20,16 +20,49 @@ namespace mozilla {
 
 template<typename T> class DefaultDelete;
 template<typename T, class D = DefaultDelete<T>> class UniquePtr;
 
 } // namespace mozilla
 
 namespace mozilla {
 
+namespace detail {
+
+struct HasPointerTypeHelper
+{
+  template <class U> static double Test(...);
+  template <class U> static char Test(typename U::pointer* = 0);
+};
+
+template <class T>
+class HasPointerType : public IntegralConstant<bool, sizeof(HasPointerTypeHelper::Test<T>(0)) == 1>
+{
+};
+
+template <class T, class D, bool = HasPointerType<D>::value>
+struct PointerTypeImpl
+{
+  typedef typename D::pointer Type;
+};
+
+template <class T, class D>
+struct PointerTypeImpl<T, D, false>
+{
+  typedef T* Type;
+};
+
+template <class T, class D>
+struct PointerType
+{
+  typedef typename PointerTypeImpl<T, typename RemoveReference<D>::Type>::Type Type;
+};
+
+} // namespace detail
+
 /**
  * UniquePtr is a smart pointer that wholly owns a resource.  Ownership may be
  * transferred out of a UniquePtr through explicit action, but otherwise the
  * resource is destroyed when the UniquePtr is destroyed.
  *
  * UniquePtr is similar to C++98's std::auto_ptr, but it improves upon auto_ptr
  * in one crucial way: it's impossible to copy a UniquePtr.  Copying an auto_ptr
  * obviously *can't* copy ownership of its singly-owned resource.  So what
@@ -149,19 +182,19 @@ namespace mozilla {
  * into a method, use a |UniquePtr| argument.  To conditionally transfer
  * ownership of a resource into a method, should the method want it, use a
  * |UniquePtr&&| argument.
  */
 template<typename T, class D>
 class UniquePtr
 {
 public:
-  typedef T* Pointer;
   typedef T ElementType;
   typedef D DeleterType;
+  typedef typename detail::PointerType<T, DeleterType>::Type Pointer;
 
 private:
   Pair<Pointer, DeleterType> mTuple;
 
   Pointer& ptr() { return mTuple.first(); }
   const Pointer& ptr() const { return mTuple.first(); }
 
   DeleterType& del() { return mTuple.second(); }
--- a/mfbt/tests/TestUniquePtr.cpp
+++ b/mfbt/tests/TestUniquePtr.cpp
@@ -73,16 +73,31 @@ ReturnUniqueA()
 
 static UniqueA
 ReturnLocalA()
 {
   UniqueA a(new A);
   return Move(a);
 }
 
+static void
+TestDeleterType()
+{
+  // Make sure UniquePtr will use its deleter's pointer type if it defines one.
+  typedef int* Ptr;
+  struct Deleter {
+    typedef Ptr pointer;
+    Deleter() {}
+    void operator()(int*p) {
+      delete p;
+    }
+  };
+  UniquePtr<Ptr, Deleter> u(new int, Deleter());
+}
+
 static bool
 TestDefaultFreeGuts()
 {
   static_assert(IsSame<NewInt::DeleterType, DefaultDelete<int> >::value,
                 "weird deleter?");
 
   NewInt n1(new int);
   CHECK(n1);
@@ -545,16 +560,18 @@ TestMakeUnique()
   UniquePtr<char[]> c1(MakeUnique<char[]>(5));
 
   return true;
 }
 
 int
 main()
 {
+  TestDeleterType();
+
   if (!TestDefaultFree()) {
     return 1;
   }
   if (!TestFreeClass()) {
     return 1;
   }
   if (!TestReferenceDeleter()) {
     return 1;