LCOV - code coverage report
Current view: top level - mfbt - UniquePtr.h (source / functions) Hit Total Coverage
Test: output.info Lines: 110 119 92.4 %
Date: 2017-07-14 16:53:18 Functions: 1558 9075 17.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : /* Smart pointer managing sole ownership of a resource. */
       8             : 
       9             : #ifndef mozilla_UniquePtr_h
      10             : #define mozilla_UniquePtr_h
      11             : 
      12             : #include "mozilla/Assertions.h"
      13             : #include "mozilla/Attributes.h"
      14             : #include "mozilla/Compiler.h"
      15             : #include "mozilla/Move.h"
      16             : #include "mozilla/Pair.h"
      17             : #include "mozilla/TypeTraits.h"
      18             : 
      19             : namespace mozilla {
      20             : 
      21             : template<typename T> class DefaultDelete;
      22             : template<typename T, class D = DefaultDelete<T>> class UniquePtr;
      23             : 
      24             : } // namespace mozilla
      25             : 
      26             : namespace mozilla {
      27             : 
      28             : namespace detail {
      29             : 
      30             : struct HasPointerTypeHelper
      31             : {
      32             :   template <class U> static double Test(...);
      33             :   template <class U> static char Test(typename U::pointer* = 0);
      34             : };
      35             : 
      36             : template <class T>
      37             : class HasPointerType : public IntegralConstant<bool, sizeof(HasPointerTypeHelper::Test<T>(0)) == 1>
      38             : {
      39             : };
      40             : 
      41             : template <class T, class D, bool = HasPointerType<D>::value>
      42             : struct PointerTypeImpl
      43             : {
      44             :   typedef typename D::pointer Type;
      45             : };
      46             : 
      47             : template <class T, class D>
      48             : struct PointerTypeImpl<T, D, false>
      49             : {
      50             :   typedef T* Type;
      51             : };
      52             : 
      53             : template <class T, class D>
      54             : struct PointerType
      55             : {
      56             :   typedef typename PointerTypeImpl<T, typename RemoveReference<D>::Type>::Type Type;
      57             : };
      58             : 
      59             : } // namespace detail
      60             : 
      61             : /**
      62             :  * UniquePtr is a smart pointer that wholly owns a resource.  Ownership may be
      63             :  * transferred out of a UniquePtr through explicit action, but otherwise the
      64             :  * resource is destroyed when the UniquePtr is destroyed.
      65             :  *
      66             :  * UniquePtr is similar to C++98's std::auto_ptr, but it improves upon auto_ptr
      67             :  * in one crucial way: it's impossible to copy a UniquePtr.  Copying an auto_ptr
      68             :  * obviously *can't* copy ownership of its singly-owned resource.  So what
      69             :  * happens if you try to copy one?  Bizarrely, ownership is implicitly
      70             :  * *transferred*, preserving single ownership but breaking code that assumes a
      71             :  * copy of an object is identical to the original.  (This is why auto_ptr is
      72             :  * prohibited in STL containers.)
      73             :  *
      74             :  * UniquePtr solves this problem by being *movable* rather than copyable.
      75             :  * Instead of passing a |UniquePtr u| directly to the constructor or assignment
      76             :  * operator, you pass |Move(u)|.  In doing so you indicate that you're *moving*
      77             :  * ownership out of |u|, into the target of the construction/assignment.  After
      78             :  * the transfer completes, |u| contains |nullptr| and may be safely destroyed.
      79             :  * This preserves single ownership but also allows UniquePtr to be moved by
      80             :  * algorithms that have been made move-safe.  (Note: if |u| is instead a
      81             :  * temporary expression, don't use |Move()|: just pass the expression, because
      82             :  * it's already move-ready.  For more information see Move.h.)
      83             :  *
      84             :  * UniquePtr is also better than std::auto_ptr in that the deletion operation is
      85             :  * customizable.  An optional second template parameter specifies a class that
      86             :  * (through its operator()(T*)) implements the desired deletion policy.  If no
      87             :  * policy is specified, mozilla::DefaultDelete<T> is used -- which will either
      88             :  * |delete| or |delete[]| the resource, depending whether the resource is an
      89             :  * array.  Custom deletion policies ideally should be empty classes (no member
      90             :  * fields, no member fields in base classes, no virtual methods/inheritance),
      91             :  * because then UniquePtr can be just as efficient as a raw pointer.
      92             :  *
      93             :  * Use of UniquePtr proceeds like so:
      94             :  *
      95             :  *   UniquePtr<int> g1; // initializes to nullptr
      96             :  *   g1.reset(new int); // switch resources using reset()
      97             :  *   g1 = nullptr; // clears g1, deletes the int
      98             :  *
      99             :  *   UniquePtr<int> g2(new int); // owns that int
     100             :  *   int* p = g2.release(); // g2 leaks its int -- still requires deletion
     101             :  *   delete p; // now freed
     102             :  *
     103             :  *   struct S { int x; S(int x) : x(x) {} };
     104             :  *   UniquePtr<S> g3, g4(new S(5));
     105             :  *   g3 = Move(g4); // g3 owns the S, g4 cleared
     106             :  *   S* p = g3.get(); // g3 still owns |p|
     107             :  *   assert(g3->x == 5); // operator-> works (if .get() != nullptr)
     108             :  *   assert((*g3).x == 5); // also operator* (again, if not cleared)
     109             :  *   Swap(g3, g4); // g4 now owns the S, g3 cleared
     110             :  *   g3.swap(g4);  // g3 now owns the S, g4 cleared
     111             :  *   UniquePtr<S> g5(Move(g3)); // g5 owns the S, g3 cleared
     112             :  *   g5.reset(); // deletes the S, g5 cleared
     113             :  *
     114             :  *   struct FreePolicy { void operator()(void* p) { free(p); } };
     115             :  *   UniquePtr<int, FreePolicy> g6(static_cast<int*>(malloc(sizeof(int))));
     116             :  *   int* ptr = g6.get();
     117             :  *   g6 = nullptr; // calls free(ptr)
     118             :  *
     119             :  * Now, carefully note a few things you *can't* do:
     120             :  *
     121             :  *   UniquePtr<int> b1;
     122             :  *   b1 = new int; // BAD: can only assign another UniquePtr
     123             :  *   int* ptr = b1; // BAD: no auto-conversion to pointer, use get()
     124             :  *
     125             :  *   UniquePtr<int> b2(b1); // BAD: can't copy a UniquePtr
     126             :  *   UniquePtr<int> b3 = b1; // BAD: can't copy-assign a UniquePtr
     127             :  *
     128             :  * (Note that changing a UniquePtr to store a direct |new| expression is
     129             :  * permitted, but usually you should use MakeUnique, defined at the end of this
     130             :  * header.)
     131             :  *
     132             :  * A few miscellaneous notes:
     133             :  *
     134             :  * UniquePtr, when not instantiated for an array type, can be move-constructed
     135             :  * and move-assigned, not only from itself but from "derived" UniquePtr<U, E>
     136             :  * instantiations where U converts to T and E converts to D.  If you want to use
     137             :  * this, you're going to have to specify a deletion policy for both UniquePtr
     138             :  * instantations, and T pretty much has to have a virtual destructor.  In other
     139             :  * words, this doesn't work:
     140             :  *
     141             :  *   struct Base { virtual ~Base() {} };
     142             :  *   struct Derived : Base {};
     143             :  *
     144             :  *   UniquePtr<Base> b1;
     145             :  *   // BAD: DefaultDelete<Base> and DefaultDelete<Derived> don't interconvert
     146             :  *   UniquePtr<Derived> d1(Move(b));
     147             :  *
     148             :  *   UniquePtr<Base> b2;
     149             :  *   UniquePtr<Derived, DefaultDelete<Base>> d2(Move(b2)); // okay
     150             :  *
     151             :  * UniquePtr is specialized for array types.  Specializing with an array type
     152             :  * creates a smart-pointer version of that array -- not a pointer to such an
     153             :  * array.
     154             :  *
     155             :  *   UniquePtr<int[]> arr(new int[5]);
     156             :  *   arr[0] = 4;
     157             :  *
     158             :  * What else is different?  Deletion of course uses |delete[]|.  An operator[]
     159             :  * is provided.  Functionality that doesn't make sense for arrays is removed.
     160             :  * The constructors and mutating methods only accept array pointers (not T*, U*
     161             :  * that converts to T*, or UniquePtr<U[]> or UniquePtr<U>) or |nullptr|.
     162             :  *
     163             :  * It's perfectly okay for a function to return a UniquePtr. This transfers
     164             :  * the UniquePtr's sole ownership of the data, to the fresh UniquePtr created
     165             :  * in the calling function, that will then solely own that data. Such functions
     166             :  * can return a local variable UniquePtr, |nullptr|, |UniquePtr(ptr)| where
     167             :  * |ptr| is a |T*|, or a UniquePtr |Move()|'d from elsewhere.
     168             :  *
     169             :  * UniquePtr will commonly be a member of a class, with lifetime equivalent to
     170             :  * that of that class.  If you want to expose the related resource, you could
     171             :  * expose a raw pointer via |get()|, but ownership of a raw pointer is
     172             :  * inherently unclear.  So it's better to expose a |const UniquePtr&| instead.
     173             :  * This prohibits mutation but still allows use of |get()| when needed (but
     174             :  * operator-> is preferred).  Of course, you can only use this smart pointer as
     175             :  * long as the enclosing class instance remains live -- no different than if you
     176             :  * exposed the |get()| raw pointer.
     177             :  *
     178             :  * To pass a UniquePtr-managed resource as a pointer, use a |const UniquePtr&|
     179             :  * argument.  To specify an inout parameter (where the method may or may not
     180             :  * take ownership of the resource, or reset it), or to specify an out parameter
     181             :  * (where simply returning a |UniquePtr| isn't possible), use a |UniquePtr&|
     182             :  * argument.  To unconditionally transfer ownership of a UniquePtr
     183             :  * into a method, use a |UniquePtr| argument.  To conditionally transfer
     184             :  * ownership of a resource into a method, should the method want it, use a
     185             :  * |UniquePtr&&| argument.
     186             :  */
     187             : template<typename T, class D>
     188             : class UniquePtr
     189             : {
     190             : public:
     191             :   typedef T ElementType;
     192             :   typedef D DeleterType;
     193             :   typedef typename detail::PointerType<T, DeleterType>::Type Pointer;
     194             : 
     195             : private:
     196             :   Pair<Pointer, DeleterType> mTuple;
     197             : 
     198      911227 :   Pointer& ptr() { return mTuple.first(); }
     199      427923 :   const Pointer& ptr() const { return mTuple.first(); }
     200             : 
     201      101175 :   DeleterType& del() { return mTuple.second(); }
     202             :   const DeleterType& del() const { return mTuple.second(); }
     203             : 
     204             : public:
     205             :   /**
     206             :    * Construct a UniquePtr containing |nullptr|.
     207             :    */
     208      136594 :   constexpr UniquePtr()
     209      136594 :     : mTuple(static_cast<Pointer>(nullptr), DeleterType())
     210             :   {
     211             :     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     212             :     static_assert(!IsReference<D>::value, "must provide a deleter instance");
     213      136593 :   }
     214             : 
     215             :   /**
     216             :    * Construct a UniquePtr containing |aPtr|.
     217             :    */
     218       74226 :   explicit UniquePtr(Pointer aPtr)
     219       74226 :     : mTuple(aPtr, DeleterType())
     220             :   {
     221             :     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     222             :     static_assert(!IsReference<D>::value, "must provide a deleter instance");
     223       74226 :   }
     224             : 
     225             :   UniquePtr(Pointer aPtr,
     226             :             typename Conditional<IsReference<D>::value,
     227             :                                  D,
     228             :                                  const D&>::Type aD1)
     229             :     : mTuple(aPtr, aD1)
     230             :   {}
     231             : 
     232             :   // If you encounter an error with MSVC10 about RemoveReference below, along
     233             :   // the lines that "more than one partial specialization matches the template
     234             :   // argument list": don't use UniquePtr<T, reference to function>!  Ideally
     235             :   // you should make deletion use the same function every time, using a
     236             :   // deleter policy:
     237             :   //
     238             :   //   // BAD, won't compile with MSVC10, deleter doesn't need to be a
     239             :   //   // variable at all
     240             :   //   typedef void (&FreeSignature)(void*);
     241             :   //   UniquePtr<int, FreeSignature> ptr((int*) malloc(sizeof(int)), free);
     242             :   //
     243             :   //   // GOOD, compiles with MSVC10, deletion behavior statically known and
     244             :   //   // optimizable
     245             :   //   struct DeleteByFreeing
     246             :   //   {
     247             :   //     void operator()(void* aPtr) { free(aPtr); }
     248             :   //   };
     249             :   //
     250             :   // If deletion really, truly, must be a variable: you might be able to work
     251             :   // around this with a deleter class that contains the function reference.
     252             :   // But this workaround is untried and untested, because variable deletion
     253             :   // behavior really isn't something you should use.
     254         627 :   UniquePtr(Pointer aPtr,
     255             :             typename RemoveReference<D>::Type&& aD2)
     256         627 :     : mTuple(aPtr, Move(aD2))
     257             :   {
     258             :     static_assert(!IsReference<D>::value,
     259             :                   "rvalue deleter can't be stored by reference");
     260         627 :   }
     261             : 
     262       86800 :   UniquePtr(UniquePtr&& aOther)
     263       86800 :     : mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
     264       86800 :   {}
     265             : 
     266             :   MOZ_IMPLICIT
     267        4125 :   UniquePtr(decltype(nullptr))
     268        4125 :     : mTuple(nullptr, DeleterType())
     269             :   {
     270             :     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     271             :     static_assert(!IsReference<D>::value, "must provide a deleter instance");
     272        4125 :   }
     273             : 
     274             :   template<typename U, class E>
     275             :   MOZ_IMPLICIT
     276         593 :   UniquePtr(UniquePtr<U, E>&& aOther,
     277             :             typename EnableIf<IsConvertible<typename UniquePtr<U, E>::Pointer,
     278             :                                             Pointer>::value &&
     279             :                               !IsArray<U>::value &&
     280             :                               (IsReference<D>::value
     281             :                                ? IsSame<D, E>::value
     282             :                                : IsConvertible<E, D>::value),
     283             :                               int>::Type aDummy = 0)
     284         593 :     : mTuple(aOther.release(), Forward<E>(aOther.get_deleter()))
     285             :   {
     286         593 :   }
     287             : 
     288      285730 :   ~UniquePtr() { reset(nullptr); }
     289             : 
     290        5986 :   UniquePtr& operator=(UniquePtr&& aOther)
     291             :   {
     292        5986 :     reset(aOther.release());
     293        5986 :     get_deleter() = Forward<DeleterType>(aOther.get_deleter());
     294        5986 :     return *this;
     295             :   }
     296             : 
     297             :   template<typename U, typename E>
     298          15 :   UniquePtr& operator=(UniquePtr<U, E>&& aOther)
     299             :   {
     300             :     static_assert(IsConvertible<typename UniquePtr<U, E>::Pointer,
     301             :                                 Pointer>::value,
     302             :                   "incompatible UniquePtr pointees");
     303             :     static_assert(!IsArray<U>::value,
     304             :                   "can't assign from UniquePtr holding an array");
     305             : 
     306          15 :     reset(aOther.release());
     307          15 :     get_deleter() = Forward<E>(aOther.get_deleter());
     308          15 :     return *this;
     309             :   }
     310             : 
     311        1963 :   UniquePtr& operator=(decltype(nullptr))
     312             :   {
     313        1963 :     reset(nullptr);
     314        1963 :     return *this;
     315             :   }
     316             : 
     317       25638 :   T& operator*() const { return *get(); }
     318      146432 :   Pointer operator->() const
     319             :   {
     320      146432 :     MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr");
     321      146432 :     return get();
     322             :   }
     323             : 
     324       75467 :   explicit operator bool() const { return get() != nullptr; }
     325             : 
     326      427923 :   Pointer get() const { return ptr(); }
     327             : 
     328      101175 :   DeleterType& get_deleter() { return del(); }
     329             :   const DeleterType& get_deleter() const { return del(); }
     330             : 
     331      161782 :   MOZ_MUST_USE Pointer release()
     332             :   {
     333      161782 :     Pointer p = ptr();
     334      161782 :     ptr() = nullptr;
     335      161781 :     return p;
     336             :   }
     337             : 
     338      293839 :   void reset(Pointer aPtr = Pointer())
     339             :   {
     340      293839 :     Pointer old = ptr();
     341      293839 :     ptr() = aPtr;
     342      293839 :     if (old != nullptr) {
     343        1781 :       get_deleter()(old);
     344             :     }
     345      293839 :   }
     346             : 
     347           0 :   void swap(UniquePtr& aOther)
     348             :   {
     349           0 :     mTuple.swap(aOther.mTuple);
     350           0 :   }
     351             : 
     352             :   UniquePtr(const UniquePtr& aOther) = delete; // construct using Move()!
     353             :   void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
     354             : };
     355             : 
     356             : // In case you didn't read the comment by the main definition (you should!): the
     357             : // UniquePtr<T[]> specialization exists to manage array pointers.  It deletes
     358             : // such pointers using delete[], it will reject construction and modification
     359             : // attempts using U* or U[].  Otherwise it works like the normal UniquePtr.
     360             : template<typename T, class D>
     361             : class UniquePtr<T[], D>
     362             : {
     363             : public:
     364             :   typedef T* Pointer;
     365             :   typedef T ElementType;
     366             :   typedef D DeleterType;
     367             : 
     368             : private:
     369             :   Pair<Pointer, DeleterType> mTuple;
     370             : 
     371             : public:
     372             :   /**
     373             :    * Construct a UniquePtr containing nullptr.
     374             :    */
     375        4280 :   constexpr UniquePtr()
     376        4280 :     : mTuple(static_cast<Pointer>(nullptr), DeleterType())
     377             :   {
     378             :     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     379             :     static_assert(!IsReference<D>::value, "must provide a deleter instance");
     380        4280 :   }
     381             : 
     382             :   /**
     383             :    * Construct a UniquePtr containing |aPtr|.
     384             :    */
     385       14799 :   explicit UniquePtr(Pointer aPtr)
     386       14799 :     : mTuple(aPtr, DeleterType())
     387             :   {
     388             :     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     389             :     static_assert(!IsReference<D>::value, "must provide a deleter instance");
     390       14799 :   }
     391             : 
     392             :   // delete[] knows how to handle *only* an array of a single class type.  For
     393             :   // delete[] to work correctly, it must know the size of each element, the
     394             :   // fields and base classes of each element requiring destruction, and so on.
     395             :   // So forbid all overloads which would end up invoking delete[] on a pointer
     396             :   // of the wrong type.
     397             :   template<typename U>
     398             :   UniquePtr(U&& aU,
     399             :             typename EnableIf<IsPointer<U>::value &&
     400             :                               IsConvertible<U, Pointer>::value,
     401             :                               int>::Type aDummy = 0)
     402             :   = delete;
     403             : 
     404             :   UniquePtr(Pointer aPtr,
     405             :             typename Conditional<IsReference<D>::value,
     406             :                                  D,
     407             :                                  const D&>::Type aD1)
     408             :     : mTuple(aPtr, aD1)
     409             :   {}
     410             : 
     411             :   // If you encounter an error with MSVC10 about RemoveReference below, along
     412             :   // the lines that "more than one partial specialization matches the template
     413             :   // argument list": don't use UniquePtr<T[], reference to function>!  See the
     414             :   // comment by this constructor in the non-T[] specialization above.
     415             :   UniquePtr(Pointer aPtr,
     416             :             typename RemoveReference<D>::Type&& aD2)
     417             :     : mTuple(aPtr, Move(aD2))
     418             :   {
     419             :     static_assert(!IsReference<D>::value,
     420             :                   "rvalue deleter can't be stored by reference");
     421             :   }
     422             : 
     423             :   // Forbidden for the same reasons as stated above.
     424             :   template<typename U, typename V>
     425             :   UniquePtr(U&& aU, V&& aV,
     426             :             typename EnableIf<IsPointer<U>::value &&
     427             :                               IsConvertible<U, Pointer>::value,
     428             :                               int>::Type aDummy = 0)
     429             :   = delete;
     430             : 
     431        4307 :   UniquePtr(UniquePtr&& aOther)
     432        4307 :     : mTuple(aOther.release(), Forward<DeleterType>(aOther.get_deleter()))
     433        4307 :   {}
     434             : 
     435             :   MOZ_IMPLICIT
     436       14434 :   UniquePtr(decltype(nullptr))
     437       14434 :     : mTuple(nullptr, DeleterType())
     438             :   {
     439             :     static_assert(!IsPointer<D>::value, "must provide a deleter instance");
     440             :     static_assert(!IsReference<D>::value, "must provide a deleter instance");
     441       14433 :   }
     442             : 
     443       27549 :   ~UniquePtr() { reset(nullptr); }
     444             : 
     445        3727 :   UniquePtr& operator=(UniquePtr&& aOther)
     446             :   {
     447        3727 :     reset(aOther.release());
     448        3727 :     get_deleter() = Forward<DeleterType>(aOther.get_deleter());
     449        3727 :     return *this;
     450             :   }
     451             : 
     452          77 :   UniquePtr& operator=(decltype(nullptr))
     453             :   {
     454          77 :     reset();
     455          77 :     return *this;
     456             :   }
     457             : 
     458       48193 :   explicit operator bool() const { return get() != nullptr; }
     459             : 
     460       18589 :   T& operator[](decltype(sizeof(int)) aIndex) const { return get()[aIndex]; }
     461      110604 :   Pointer get() const { return mTuple.first(); }
     462             : 
     463       11763 :   DeleterType& get_deleter() { return mTuple.second(); }
     464             :   const DeleterType& get_deleter() const { return mTuple.second(); }
     465             : 
     466       13512 :   MOZ_MUST_USE Pointer release()
     467             :   {
     468       13512 :     Pointer p = mTuple.first();
     469       13512 :     mTuple.first() = nullptr;
     470       13512 :     return p;
     471             :   }
     472             : 
     473        4507 :   void reset(Pointer aPtr = Pointer())
     474             :   {
     475        4507 :     Pointer old = mTuple.first();
     476        4507 :     mTuple.first() = aPtr;
     477        4507 :     if (old != nullptr) {
     478         204 :       mTuple.second()(old);
     479             :     }
     480        4507 :   }
     481             : 
     482       27549 :   void reset(decltype(nullptr))
     483             :   {
     484       27549 :     Pointer old = mTuple.first();
     485       27549 :     mTuple.first() = nullptr;
     486       27549 :     if (old != nullptr) {
     487        6377 :       mTuple.second()(old);
     488             :     }
     489       27549 :   }
     490             : 
     491             :   template<typename U>
     492             :   void reset(U) = delete;
     493             : 
     494           0 :   void swap(UniquePtr& aOther) { mTuple.swap(aOther.mTuple); }
     495             : 
     496             :   UniquePtr(const UniquePtr& aOther) = delete; // construct using Move()!
     497             :   void operator=(const UniquePtr& aOther) = delete; // assign using Move()!
     498             : };
     499             : 
     500             : /**
     501             :  * A default deletion policy using plain old operator delete.
     502             :  *
     503             :  * Note that this type can be specialized, but authors should beware of the risk
     504             :  * that the specialization may at some point cease to match (either because it
     505             :  * gets moved to a different compilation unit or the signature changes). If the
     506             :  * non-specialized (|delete|-based) version compiles for that type but does the
     507             :  * wrong thing, bad things could happen.
     508             :  *
     509             :  * This is a non-issue for types which are always incomplete (i.e. opaque handle
     510             :  * types), since |delete|-ing such a type will always trigger a compilation
     511             :  * error.
     512             :  */
     513             : template<typename T>
     514             : class DefaultDelete
     515             : {
     516             : public:
     517       22083 :   constexpr DefaultDelete() {}
     518             : 
     519             :   template<typename U>
     520         608 :   MOZ_IMPLICIT DefaultDelete(const DefaultDelete<U>& aOther,
     521             :                              typename EnableIf<mozilla::IsConvertible<U*, T*>::value,
     522             :                                                int>::Type aDummy = 0)
     523         608 :   {}
     524             : 
     525        1748 :   void operator()(T* aPtr) const
     526             :   {
     527             :     static_assert(sizeof(T) > 0, "T must be complete");
     528        1748 :     delete aPtr;
     529        1748 :   }
     530             : };
     531             : 
     532             : /** A default deletion policy using operator delete[]. */
     533             : template<typename T>
     534             : class DefaultDelete<T[]>
     535             : {
     536             : public:
     537        2767 :   constexpr DefaultDelete() {}
     538             : 
     539         957 :   void operator()(T* aPtr) const
     540             :   {
     541             :     static_assert(sizeof(T) > 0, "T must be complete");
     542         957 :     delete[] aPtr;
     543         957 :   }
     544             : 
     545             :   template<typename U>
     546             :   void operator()(U* aPtr) const = delete;
     547             : };
     548             : 
     549             : template<typename T, class D>
     550             : void
     551           0 : Swap(UniquePtr<T, D>& aX, UniquePtr<T, D>& aY)
     552             : {
     553           0 :   aX.swap(aY);
     554           0 : }
     555             : 
     556             : template<typename T, class D, typename U, class E>
     557             : bool
     558         935 : operator==(const UniquePtr<T, D>& aX, const UniquePtr<U, E>& aY)
     559             : {
     560         935 :   return aX.get() == aY.get();
     561             : }
     562             : 
     563             : template<typename T, class D, typename U, class E>
     564             : bool
     565             : operator!=(const UniquePtr<T, D>& aX, const UniquePtr<U, E>& aY)
     566             : {
     567             :   return aX.get() != aY.get();
     568             : }
     569             : 
     570             : template<typename T, class D>
     571             : bool
     572          35 : operator==(const UniquePtr<T, D>& aX, decltype(nullptr))
     573             : {
     574          35 :   return !aX;
     575             : }
     576             : 
     577             : template<typename T, class D>
     578             : bool
     579           0 : operator==(decltype(nullptr), const UniquePtr<T, D>& aX)
     580             : {
     581           0 :   return !aX;
     582             : }
     583             : 
     584             : template<typename T, class D>
     585             : bool
     586        6085 : operator!=(const UniquePtr<T, D>& aX, decltype(nullptr))
     587             : {
     588        6085 :   return bool(aX);
     589             : }
     590             : 
     591             : template<typename T, class D>
     592             : bool
     593             : operator!=(decltype(nullptr), const UniquePtr<T, D>& aX)
     594             : {
     595             :   return bool(aX);
     596             : }
     597             : 
     598             : // No operator<, operator>, operator<=, operator>= for now because simplicity.
     599             : 
     600             : namespace detail {
     601             : 
     602             : template<typename T>
     603             : struct UniqueSelector
     604             : {
     605             :   typedef UniquePtr<T> SingleObject;
     606             : };
     607             : 
     608             : template<typename T>
     609             : struct UniqueSelector<T[]>
     610             : {
     611             :   typedef UniquePtr<T[]> UnknownBound;
     612             : };
     613             : 
     614             : template<typename T, decltype(sizeof(int)) N>
     615             : struct UniqueSelector<T[N]>
     616             : {
     617             :   typedef UniquePtr<T[N]> KnownBound;
     618             : };
     619             : 
     620             : } // namespace detail
     621             : 
     622             : /**
     623             :  * MakeUnique is a helper function for allocating new'd objects and arrays,
     624             :  * returning a UniquePtr containing the resulting pointer.  The semantics of
     625             :  * MakeUnique<Type>(...) are as follows.
     626             :  *
     627             :  *   If Type is an array T[n]:
     628             :  *     Disallowed, deleted, no overload for you!
     629             :  *   If Type is an array T[]:
     630             :  *     MakeUnique<T[]>(size_t) is the only valid overload.  The pointer returned
     631             :  *     is as if by |new T[n]()|, which value-initializes each element.  (If T
     632             :  *     isn't a class type, this will zero each element.  If T is a class type,
     633             :  *     then roughly speaking, each element will be constructed using its default
     634             :  *     constructor.  See C++11 [dcl.init]p7 for the full gory details.)
     635             :  *   If Type is non-array T:
     636             :  *     The arguments passed to MakeUnique<T>(...) are forwarded into a
     637             :  *     |new T(...)| call, initializing the T as would happen if executing
     638             :  *     |T(...)|.
     639             :  *
     640             :  * There are various benefits to using MakeUnique instead of |new| expressions.
     641             :  *
     642             :  * First, MakeUnique eliminates use of |new| from code entirely.  If objects are
     643             :  * only created through UniquePtr, then (assuming all explicit release() calls
     644             :  * are safe, including transitively, and no type-safety casting funniness)
     645             :  * correctly maintained ownership of the UniquePtr guarantees no leaks are
     646             :  * possible.  (This pays off best if a class is only ever created through a
     647             :  * factory method on the class, using a private constructor.)
     648             :  *
     649             :  * Second, initializing a UniquePtr using a |new| expression requires repeating
     650             :  * the name of the new'd type, whereas MakeUnique in concert with the |auto|
     651             :  * keyword names it only once:
     652             :  *
     653             :  *   UniquePtr<char> ptr1(new char()); // repetitive
     654             :  *   auto ptr2 = MakeUnique<char>();   // shorter
     655             :  *
     656             :  * Of course this assumes the reader understands the operation MakeUnique
     657             :  * performs.  In the long run this is probably a reasonable assumption.  In the
     658             :  * short run you'll have to use your judgment about what readers can be expected
     659             :  * to know, or to quickly look up.
     660             :  *
     661             :  * Third, a call to MakeUnique can be assigned directly to a UniquePtr.  In
     662             :  * contrast you can't assign a pointer into a UniquePtr without using the
     663             :  * cumbersome reset().
     664             :  *
     665             :  *   UniquePtr<char> p;
     666             :  *   p = new char;           // ERROR
     667             :  *   p.reset(new char);      // works, but fugly
     668             :  *   p = MakeUnique<char>(); // preferred
     669             :  *
     670             :  * (And third, although not relevant to Mozilla: MakeUnique is exception-safe.
     671             :  * An exception thrown after |new T| succeeds will leak that memory, unless the
     672             :  * pointer is assigned to an object that will manage its ownership.  UniquePtr
     673             :  * ably serves this function.)
     674             :  */
     675             : 
     676             : template<typename T, typename... Args>
     677             : typename detail::UniqueSelector<T>::SingleObject
     678        4125 : MakeUnique(Args&&... aArgs)
     679             : {
     680        5826 :   return UniquePtr<T>(new T(Forward<Args>(aArgs)...));
     681             : }
     682             : 
     683             : template<typename T>
     684             : typename detail::UniqueSelector<T>::UnknownBound
     685         963 : MakeUnique(decltype(sizeof(int)) aN)
     686             : {
     687             :   typedef typename RemoveExtent<T>::Type ArrayType;
     688        1926 :   return UniquePtr<T>(new ArrayType[aN]());
     689             : }
     690             : 
     691             : template<typename T, typename... Args>
     692             : typename detail::UniqueSelector<T>::KnownBound
     693             : MakeUnique(Args&&... aArgs) = delete;
     694             : 
     695             : } // namespace mozilla
     696             : 
     697             : #endif /* mozilla_UniquePtr_h */

Generated by: LCOV version 1.13