unique_ptr.h

Go to the documentation of this file.
00001 // unique_ptr implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file unique_ptr.h
00026  *  This is an internal header file, included by other library headers.
00027  *  You should not attempt to use it directly.
00028  */
00029 
00030 #ifndef _UNIQUE_PTR_H
00031 #define _UNIQUE_PTR_H 1
00032 
00033 #include <bits/c++config.h>
00034 #include <debug/debug.h>
00035 #include <type_traits>
00036 #include <utility>
00037 #include <tuple>
00038 
00039 _GLIBCXX_BEGIN_NAMESPACE(std)
00040 
00041   /**
00042    * @addtogroup pointer_abstractions
00043    * @{
00044    */
00045 
00046   /// Primary template, default_delete.
00047   template<typename _Tp> 
00048     struct default_delete
00049       {
00050     default_delete() { }
00051 
00052     template<typename _Up, typename = typename
00053          std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type>
00054       default_delete(const default_delete<_Up>&) { }
00055 
00056     void
00057     operator()(_Tp* __ptr) const
00058     {
00059       static_assert(sizeof(_Tp)>0,
00060             "can't delete pointer to incomplete type");
00061       delete __ptr;
00062     }
00063     };
00064 
00065   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00066   // DR 740 - omit specialization for array objects with a compile time length
00067   /// Specialization, default_delete.
00068   template<typename _Tp> 
00069     struct default_delete<_Tp[]>
00070     {
00071       void
00072       operator()(_Tp* __ptr) const
00073       {
00074     static_assert(sizeof(_Tp)>0,
00075               "can't delete pointer to incomplete type");
00076     delete [] __ptr;
00077       }
00078     };
00079 
00080   /// 20.7.12.2 unique_ptr for single objects.
00081   template <typename _Tp, typename _Dp = default_delete<_Tp> > 
00082     class unique_ptr
00083     {
00084       typedef std::tuple<_Tp*, _Dp>  __tuple_type;
00085 
00086       // use SFINAE to determine whether _Del::pointer exists
00087       class _Pointer
00088       {
00089     template<typename _Up>
00090       static typename _Up::pointer __test(typename _Up::pointer*);
00091 
00092     template<typename _Up>
00093       static _Tp* __test(...);
00094 
00095     typedef typename remove_reference<_Dp>::type _Del;
00096 
00097       public:
00098     typedef decltype( __test<_Del>(0) ) type;
00099       };
00100 
00101     public:
00102       typedef typename _Pointer::type   pointer;
00103       typedef _Tp                       element_type;
00104       typedef _Dp                       deleter_type;
00105 
00106       // Constructors.
00107       unique_ptr()
00108       : _M_t(pointer(), deleter_type())
00109       { static_assert(!std::is_pointer<deleter_type>::value,
00110               "constructed with null function pointer deleter"); }
00111 
00112       explicit
00113       unique_ptr(pointer __p)
00114       : _M_t(__p, deleter_type())
00115       { static_assert(!std::is_pointer<deleter_type>::value,
00116              "constructed with null function pointer deleter"); }
00117 
00118       unique_ptr(pointer __p,
00119           typename std::conditional<std::is_reference<deleter_type>::value, 
00120             deleter_type, const deleter_type&>::type __d)
00121       : _M_t(__p, __d) { }
00122 
00123       unique_ptr(pointer __p,
00124           typename std::remove_reference<deleter_type>::type&& __d)
00125       : _M_t(std::move(__p), std::move(__d))
00126       { static_assert(!std::is_reference<deleter_type>::value, 
00127               "rvalue deleter bound to reference"); }
00128 
00129       unique_ptr(nullptr_t)
00130       : _M_t(pointer(), deleter_type())
00131       { }
00132 
00133       // Move constructors.
00134       unique_ptr(unique_ptr&& __u) 
00135       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00136 
00137       template<typename _Up, typename _Ep, typename = typename
00138     std::enable_if
00139       <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
00140                    pointer>::value
00141        && !std::is_array<_Up>::value
00142        && ((std::is_reference<_Dp>::value
00143         && std::is_same<_Ep, _Dp>::value)
00144            || (!std::is_reference<_Dp>::value
00145            && std::is_convertible<_Ep, _Dp>::value))>
00146              ::type>
00147         unique_ptr(unique_ptr<_Up, _Ep>&& __u) 
00148         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00149     { }
00150 
00151 #if _GLIBCXX_DEPRECATED
00152       template<typename _Up, typename = typename
00153     std::enable_if<std::is_convertible<_Up*, _Tp*>::value
00154                && std::is_same<_Dp,
00155                        default_delete<_Tp>>::value>::type>
00156         unique_ptr(auto_ptr<_Up>&& __u)
00157     : _M_t(__u.release(), deleter_type()) { }
00158 #endif
00159 
00160       // Destructor.
00161       ~unique_ptr() { reset(); }
00162 
00163       // Assignment.
00164       unique_ptr&
00165       operator=(unique_ptr&& __u)
00166       { 
00167         reset(__u.release()); 
00168         get_deleter() = std::move(__u.get_deleter()); 
00169         return *this;
00170       }
00171 
00172       template<typename _Up, typename _Ep, typename = typename
00173         std::enable_if
00174       <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
00175                    pointer>::value
00176        && !std::is_array<_Up>::value>::type> 
00177         unique_ptr&
00178         operator=(unique_ptr<_Up, _Ep>&& __u)
00179     {
00180           reset(__u.release()); 
00181           get_deleter() = std::move(__u.get_deleter()); 
00182           return *this;
00183         }
00184 
00185       unique_ptr&
00186       operator=(nullptr_t)
00187       {
00188     reset();
00189     return *this;
00190       }
00191 
00192       // Observers.
00193       typename std::add_lvalue_reference<element_type>::type
00194       operator*() const
00195       {
00196     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00197     return *get();
00198       }
00199 
00200       pointer
00201       operator->() const
00202       {
00203     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00204     return get();
00205       }
00206 
00207       pointer
00208       get() const
00209       { return std::get<0>(_M_t); }
00210 
00211       deleter_type&
00212       get_deleter()
00213       { return std::get<1>(_M_t); }
00214 
00215       const deleter_type&
00216       get_deleter() const
00217       { return std::get<1>(_M_t); }
00218 
00219       explicit operator bool() const
00220       { return get() == pointer() ? false : true; }
00221 
00222       // Modifiers.
00223       pointer
00224       release() 
00225       {
00226     pointer __p = get();
00227     std::get<0>(_M_t) = pointer();
00228     return __p;
00229       }
00230 
00231       void
00232       reset(pointer __p = pointer())
00233       {
00234     using std::swap;
00235     swap(std::get<0>(_M_t), __p);
00236     if (__p != pointer())
00237       get_deleter()(__p);
00238       }
00239 
00240       void
00241       swap(unique_ptr& __u)
00242       {
00243     using std::swap;
00244     swap(_M_t, __u._M_t);
00245       }
00246 
00247       // Disable copy from lvalue.
00248       unique_ptr(const unique_ptr&) = delete;
00249       unique_ptr& operator=(const unique_ptr&) = delete;
00250 
00251     private:
00252       __tuple_type _M_t;
00253   };
00254  
00255   /// 20.7.12.3 unique_ptr for array objects with a runtime length
00256   // [unique.ptr.runtime]
00257   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00258   // DR 740 - omit specialization for array objects with a compile time length
00259   template<typename _Tp, typename _Dp>
00260     class unique_ptr<_Tp[], _Dp>
00261     {
00262       typedef std::tuple<_Tp*, _Dp>  __tuple_type;
00263 
00264     public:
00265       typedef _Tp*               pointer;
00266       typedef _Tp                element_type;      
00267       typedef _Dp        deleter_type;
00268 
00269       // Constructors.
00270       unique_ptr()
00271       : _M_t(pointer(), deleter_type())
00272       { static_assert(!std::is_pointer<deleter_type>::value,
00273               "constructed with null function pointer deleter"); }
00274 
00275       explicit
00276       unique_ptr(pointer __p)
00277       : _M_t(__p, deleter_type())
00278       { static_assert(!std::is_pointer<deleter_type>::value,
00279               "constructed with null function pointer deleter"); }
00280 
00281       unique_ptr(pointer __p,
00282           typename std::conditional<std::is_reference<deleter_type>::value, 
00283               deleter_type, const deleter_type&>::type __d) 
00284       : _M_t(__p, __d) { }
00285 
00286       unique_ptr(pointer __p,
00287          typename std::remove_reference<deleter_type>::type && __d)
00288       : _M_t(std::move(__p), std::move(__d))
00289       { static_assert(!std::is_reference<deleter_type>::value, 
00290               "rvalue deleter bound to reference"); }
00291 
00292       /* TODO: use delegating constructor */
00293       unique_ptr(nullptr_t)
00294       : _M_t(pointer(), deleter_type())
00295       { }
00296 
00297       // Move constructors.
00298       unique_ptr(unique_ptr&& __u) 
00299       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00300 
00301       template<typename _Up, typename _Ep> 
00302         unique_ptr(unique_ptr<_Up, _Ep>&& __u) 
00303     : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00304     { }
00305 
00306       // Destructor.
00307       ~unique_ptr() { reset(); }
00308 
00309       // Assignment.
00310       unique_ptr&
00311       operator=(unique_ptr&& __u)
00312       {
00313     reset(__u.release());
00314     get_deleter() = std::move(__u.get_deleter()); 
00315     return *this; 
00316       }
00317 
00318       template<typename _Up, typename _Ep> 
00319         unique_ptr&
00320         operator=(unique_ptr<_Up, _Ep>&& __u)
00321     {
00322           reset(__u.release());
00323           get_deleter() = std::move(__u.get_deleter()); 
00324           return *this;
00325         }
00326 
00327       unique_ptr&
00328       operator=(nullptr_t)
00329       {
00330     reset();
00331     return *this;
00332       }
00333 
00334       // Observers.
00335       typename std::add_lvalue_reference<element_type>::type 
00336       operator[](size_t __i) const 
00337       {
00338     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00339     return get()[__i];
00340       }
00341 
00342       pointer
00343       get() const
00344       { return std::get<0>(_M_t); }
00345 
00346       deleter_type& 
00347       get_deleter()
00348       { return std::get<1>(_M_t); }
00349 
00350       const deleter_type&
00351       get_deleter() const
00352       { return std::get<1>(_M_t); }    
00353 
00354       explicit operator bool() const 
00355       { return get() == pointer() ? false : true; }
00356     
00357       // Modifiers.
00358       pointer
00359       release() 
00360       {
00361     pointer __p = get();
00362     std::get<0>(_M_t) = pointer();
00363     return __p;
00364       }
00365 
00366       void
00367       reset(pointer __p = pointer()) 
00368       {
00369     using std::swap;
00370     swap(std::get<0>(_M_t), __p);
00371     if (__p != nullptr)
00372       get_deleter()(__p);
00373       }
00374 
00375       void
00376       reset(nullptr_t)
00377       {
00378     pointer __p = get();
00379     std::get<0>(_M_t) = pointer();
00380     if (__p != nullptr)
00381       get_deleter()(__p);
00382       }
00383 
00384       // DR 821.
00385       template<typename _Up>
00386         void reset(_Up) = delete;
00387 
00388       void
00389       swap(unique_ptr& __u)
00390       {
00391     using std::swap;
00392     swap(_M_t, __u._M_t);
00393       }
00394 
00395       // Disable copy from lvalue.
00396       unique_ptr(const unique_ptr&) = delete;
00397       unique_ptr& operator=(const unique_ptr&) = delete;
00398 
00399       // Disable construction from convertible pointer types.
00400       // (N2315 - 20.6.5.3.1)
00401       template<typename _Up>
00402         unique_ptr(_Up*, typename
00403            std::conditional<std::is_reference<deleter_type>::value,
00404            deleter_type, const deleter_type&>::type,
00405            typename std::enable_if<std::is_convertible<_Up*, 
00406            pointer>::value>::type* = 0) = delete;
00407 
00408       template<typename _Up>
00409         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
00410            typename std::enable_if<std::is_convertible<_Up*, 
00411            pointer>::value>::type* = 0) = delete;
00412 
00413       template<typename _Up>
00414         explicit
00415         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 
00416            pointer>::value>::type* = 0) = delete;
00417 
00418     private:
00419       __tuple_type _M_t;
00420   };
00421   
00422   template<typename _Tp, typename _Dp> 
00423     inline void
00424     swap(unique_ptr<_Tp, _Dp>& __x,
00425      unique_ptr<_Tp, _Dp>& __y)
00426     { __x.swap(__y); }
00427 
00428   template<typename _Tp, typename _Dp,
00429        typename _Up, typename _Ep>
00430     inline bool
00431     operator==(const unique_ptr<_Tp, _Dp>& __x,
00432            const unique_ptr<_Up, _Ep>& __y)
00433     { return __x.get() == __y.get(); }
00434 
00435   template<typename _Tp, typename _Dp>
00436     inline bool
00437     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00438     { return __x.get() == nullptr; }
00439 
00440   template<typename _Tp, typename _Dp>
00441     inline bool
00442     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
00443     { return nullptr == __y.get(); }
00444 
00445   template<typename _Tp, typename _Dp,
00446        typename _Up, typename _Ep>
00447     inline bool
00448     operator!=(const unique_ptr<_Tp, _Dp>& __x,
00449            const unique_ptr<_Up, _Ep>& __y)
00450     { return !(__x.get() == __y.get()); }
00451 
00452   template<typename _Tp, typename _Dp>
00453     inline bool
00454     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00455     { return __x.get() != nullptr; }
00456 
00457   template<typename _Tp, typename _Dp>
00458     inline bool
00459     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
00460     { return nullptr != __y.get(); }
00461 
00462   template<typename _Tp, typename _Dp,
00463        typename _Up, typename _Ep>
00464     inline bool
00465     operator<(const unique_ptr<_Tp, _Dp>& __x,
00466           const unique_ptr<_Up, _Ep>& __y)
00467     { return __x.get() < __y.get(); }
00468 
00469   template<typename _Tp, typename _Dp,
00470        typename _Up, typename _Ep>
00471     inline bool
00472     operator<=(const unique_ptr<_Tp, _Dp>& __x,
00473            const unique_ptr<_Up, _Ep>& __y)
00474     { return !(__y.get() < __x.get()); }
00475 
00476   template<typename _Tp, typename _Dp,
00477        typename _Up, typename _Ep>
00478     inline bool
00479     operator>(const unique_ptr<_Tp, _Dp>& __x,
00480           const unique_ptr<_Up, _Ep>& __y)
00481     { return __y.get() < __x.get(); }
00482 
00483   template<typename _Tp, typename _Dp,
00484        typename _Up, typename _Ep>
00485     inline bool
00486     operator>=(const unique_ptr<_Tp, _Dp>& __x,
00487            const unique_ptr<_Up, _Ep>& __y)
00488     { return !(__x.get() < __y.get()); }
00489 
00490   /// std::hash specialization for unique_ptr.
00491   template<typename _Tp, typename _Dp>
00492     struct hash<unique_ptr<_Tp, _Dp>>
00493     : public std::unary_function<unique_ptr<_Tp, _Dp>, size_t>
00494     {
00495       size_t
00496       operator()(const unique_ptr<_Tp, _Dp>& __u) const
00497       {
00498     typedef unique_ptr<_Tp, _Dp> _UP;
00499     return std::hash<typename _UP::pointer>()(__u.get());
00500       }
00501     };
00502 
00503   // @} group pointer_abstractions
00504 
00505 _GLIBCXX_END_NAMESPACE
00506 
00507 #endif /* _UNIQUE_PTR_H */