libstdc++
unique_ptr.h
Go to the documentation of this file.
00001 // unique_ptr implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2008-2013 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 bits/unique_ptr.h
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{memory}
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 namespace std _GLIBCXX_VISIBILITY(default)
00040 {
00041 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00042 
00043   /**
00044    * @addtogroup pointer_abstractions
00045    * @{
00046    */
00047 
00048 #if _GLIBCXX_USE_DEPRECATED
00049   template<typename> class auto_ptr;
00050 #endif
00051 
00052   /// Primary template, default_delete.
00053   template<typename _Tp>
00054     struct default_delete
00055     {
00056       constexpr default_delete() noexcept = default;
00057 
00058       template<typename _Up, typename = typename
00059            enable_if<is_convertible<_Up*, _Tp*>::value>::type>
00060         default_delete(const default_delete<_Up>&) noexcept { }
00061 
00062       void
00063       operator()(_Tp* __ptr) const
00064       {
00065     static_assert(sizeof(_Tp)>0,
00066               "can't delete pointer to incomplete type");
00067     delete __ptr;
00068       }
00069     };
00070 
00071   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00072   // DR 740 - omit specialization for array objects with a compile time length
00073   /// Specialization, default_delete.
00074   template<typename _Tp>
00075     struct default_delete<_Tp[]>
00076     {
00077     private:
00078       template<typename _Up>
00079     using __remove_cv = typename remove_cv<_Up>::type;
00080 
00081       // Like is_base_of<_Tp, _Up> but false if unqualified types are the same
00082       template<typename _Up>
00083     using __is_derived_Tp
00084       = __and_< is_base_of<_Tp, _Up>,
00085             __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
00086 
00087     public:
00088       constexpr default_delete() noexcept = default;
00089 
00090       template<typename _Up, typename = typename
00091            enable_if<!__is_derived_Tp<_Up>::value>::type>
00092         default_delete(const default_delete<_Up[]>&) noexcept { }
00093 
00094       void
00095       operator()(_Tp* __ptr) const
00096       {
00097     static_assert(sizeof(_Tp)>0,
00098               "can't delete pointer to incomplete type");
00099     delete [] __ptr;
00100       }
00101 
00102       template<typename _Up>
00103     typename enable_if<__is_derived_Tp<_Up>::value>::type
00104     operator()(_Up*) const = delete;
00105     };
00106 
00107   /// 20.7.1.2 unique_ptr for single objects.
00108   template <typename _Tp, typename _Dp = default_delete<_Tp> >
00109     class unique_ptr
00110     {
00111       // use SFINAE to determine whether _Del::pointer exists
00112       class _Pointer
00113       {
00114     template<typename _Up>
00115       static typename _Up::pointer __test(typename _Up::pointer*);
00116 
00117     template<typename _Up>
00118       static _Tp* __test(...);
00119 
00120     typedef typename remove_reference<_Dp>::type _Del;
00121 
00122       public:
00123     typedef decltype(__test<_Del>(0)) type;
00124       };
00125 
00126       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
00127       __tuple_type                                      _M_t;
00128 
00129     public:
00130       typedef typename _Pointer::type   pointer;
00131       typedef _Tp                       element_type;
00132       typedef _Dp                       deleter_type;
00133 
00134       // Constructors.
00135       constexpr unique_ptr() noexcept
00136       : _M_t()
00137       { static_assert(!is_pointer<deleter_type>::value,
00138              "constructed with null function pointer deleter"); }
00139 
00140       explicit
00141       unique_ptr(pointer __p) noexcept
00142       : _M_t(__p, deleter_type())
00143       { static_assert(!is_pointer<deleter_type>::value,
00144              "constructed with null function pointer deleter"); }
00145 
00146       unique_ptr(pointer __p,
00147       typename conditional<is_reference<deleter_type>::value,
00148         deleter_type, const deleter_type&>::type __d) noexcept
00149       : _M_t(__p, __d) { }
00150 
00151       unique_ptr(pointer __p,
00152       typename remove_reference<deleter_type>::type&& __d) noexcept
00153       : _M_t(std::move(__p), std::move(__d))
00154       { static_assert(!std::is_reference<deleter_type>::value,
00155               "rvalue deleter bound to reference"); }
00156 
00157       constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
00158 
00159       // Move constructors.
00160       unique_ptr(unique_ptr&& __u) noexcept
00161       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00162 
00163       template<typename _Up, typename _Ep, typename = _Require<
00164            is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
00165            __not_<is_array<_Up>>,
00166            typename conditional<is_reference<_Dp>::value,
00167                     is_same<_Ep, _Dp>,
00168                     is_convertible<_Ep, _Dp>>::type>>
00169     unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
00170     : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
00171     { }
00172 
00173 #if _GLIBCXX_USE_DEPRECATED
00174       template<typename _Up, typename = _Require<
00175            is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
00176     unique_ptr(auto_ptr<_Up>&& __u) noexcept;
00177 #endif
00178 
00179       // Destructor.
00180       ~unique_ptr() noexcept
00181       {
00182     auto& __ptr = std::get<0>(_M_t);
00183     if (__ptr != nullptr)
00184       get_deleter()(__ptr);
00185     __ptr = pointer();
00186       }
00187 
00188       // Assignment.
00189       unique_ptr&
00190       operator=(unique_ptr&& __u) noexcept
00191       {
00192     reset(__u.release());
00193     get_deleter() = std::forward<deleter_type>(__u.get_deleter());
00194     return *this;
00195       }
00196 
00197       template<typename _Up, typename _Ep>
00198     typename enable_if< __and_<
00199       is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
00200       __not_<is_array<_Up>>
00201       >::value,
00202       unique_ptr&>::type
00203     operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
00204     {
00205       reset(__u.release());
00206       get_deleter() = std::forward<_Ep>(__u.get_deleter());
00207       return *this;
00208     }
00209 
00210       unique_ptr&
00211       operator=(nullptr_t) noexcept
00212       {
00213     reset();
00214     return *this;
00215       }
00216 
00217       // Observers.
00218       typename add_lvalue_reference<element_type>::type
00219       operator*() const
00220       {
00221     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00222     return *get();
00223       }
00224 
00225       pointer
00226       operator->() const noexcept
00227       {
00228     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00229     return get();
00230       }
00231 
00232       pointer
00233       get() const noexcept
00234       { return std::get<0>(_M_t); }
00235 
00236       deleter_type&
00237       get_deleter() noexcept
00238       { return std::get<1>(_M_t); }
00239 
00240       const deleter_type&
00241       get_deleter() const noexcept
00242       { return std::get<1>(_M_t); }
00243 
00244       explicit operator bool() const noexcept
00245       { return get() == pointer() ? false : true; }
00246 
00247       // Modifiers.
00248       pointer
00249       release() noexcept
00250       {
00251     pointer __p = get();
00252     std::get<0>(_M_t) = pointer();
00253     return __p;
00254       }
00255 
00256       void
00257       reset(pointer __p = pointer()) noexcept
00258       {
00259     using std::swap;
00260     swap(std::get<0>(_M_t), __p);
00261     if (__p != pointer())
00262       get_deleter()(__p);
00263       }
00264 
00265       void
00266       swap(unique_ptr& __u) noexcept
00267       {
00268     using std::swap;
00269     swap(_M_t, __u._M_t);
00270       }
00271 
00272       // Disable copy from lvalue.
00273       unique_ptr(const unique_ptr&) = delete;
00274       unique_ptr& operator=(const unique_ptr&) = delete;
00275   };
00276 
00277   /// 20.7.1.3 unique_ptr for array objects with a runtime length
00278   // [unique.ptr.runtime]
00279   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00280   // DR 740 - omit specialization for array objects with a compile time length
00281   template<typename _Tp, typename _Dp>
00282     class unique_ptr<_Tp[], _Dp>
00283     {
00284       // use SFINAE to determine whether _Del::pointer exists
00285       class _Pointer
00286       {
00287     template<typename _Up>
00288       static typename _Up::pointer __test(typename _Up::pointer*);
00289 
00290     template<typename _Up>
00291       static _Tp* __test(...);
00292 
00293     typedef typename remove_reference<_Dp>::type _Del;
00294 
00295       public:
00296     typedef decltype(__test<_Del>(0)) type;
00297       };
00298 
00299       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
00300       __tuple_type                                      _M_t;
00301 
00302       template<typename _Up>
00303     using __remove_cv = typename remove_cv<_Up>::type;
00304 
00305       // like is_base_of<_Tp, _Up> but false if unqualified types are the same
00306       template<typename _Up>
00307     using __is_derived_Tp
00308       = __and_< is_base_of<_Tp, _Up>,
00309             __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
00310 
00311       template<typename _Up, typename _Ep,
00312            typename _Tp_pointer = typename _Pointer::type,
00313            typename _Up_pointer = typename unique_ptr<_Up, _Ep>::pointer>
00314     using __safe_conversion = __and_<
00315         is_convertible<_Up_pointer, _Tp_pointer>,
00316         is_array<_Up>,
00317         __or_<__not_<is_pointer<_Up_pointer>>,
00318           __not_<is_pointer<_Tp_pointer>>,
00319           __not_<__is_derived_Tp<typename remove_extent<_Up>::type>>
00320         >
00321       >;
00322 
00323     public:
00324       typedef typename _Pointer::type   pointer;
00325       typedef _Tp           element_type;
00326       typedef _Dp                       deleter_type;
00327 
00328       // Constructors.
00329       constexpr unique_ptr() noexcept
00330       : _M_t()
00331       { static_assert(!std::is_pointer<deleter_type>::value,
00332               "constructed with null function pointer deleter"); }
00333 
00334       explicit
00335       unique_ptr(pointer __p) noexcept
00336       : _M_t(__p, deleter_type())
00337       { static_assert(!is_pointer<deleter_type>::value,
00338               "constructed with null function pointer deleter"); }
00339 
00340       template<typename _Up, typename = _Require<is_pointer<pointer>,
00341            is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
00342     explicit
00343     unique_ptr(_Up* __p) = delete;
00344 
00345       unique_ptr(pointer __p,
00346       typename conditional<is_reference<deleter_type>::value,
00347           deleter_type, const deleter_type&>::type __d) noexcept
00348       : _M_t(__p, __d) { }
00349 
00350       unique_ptr(pointer __p, typename
00351          remove_reference<deleter_type>::type&& __d) noexcept
00352       : _M_t(std::move(__p), std::move(__d))
00353       { static_assert(!is_reference<deleter_type>::value,
00354               "rvalue deleter bound to reference"); }
00355 
00356       // Move constructor.
00357       unique_ptr(unique_ptr&& __u) noexcept
00358       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00359 
00360       constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
00361 
00362       template<typename _Up, typename _Ep,
00363            typename = _Require<__safe_conversion<_Up, _Ep>,
00364          typename conditional<is_reference<_Dp>::value,
00365                       is_same<_Ep, _Dp>,
00366                       is_convertible<_Ep, _Dp>>::type
00367            >>
00368     unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
00369     : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
00370     { }
00371 
00372       // Destructor.
00373       ~unique_ptr()
00374       {
00375     auto& __ptr = std::get<0>(_M_t);
00376     if (__ptr != nullptr)
00377       get_deleter()(__ptr);
00378     __ptr = pointer();
00379       }
00380 
00381       // Assignment.
00382       unique_ptr&
00383       operator=(unique_ptr&& __u) noexcept
00384       {
00385     reset(__u.release());
00386     get_deleter() = std::forward<deleter_type>(__u.get_deleter());
00387     return *this;
00388       }
00389 
00390       template<typename _Up, typename _Ep>
00391     typename
00392     enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type
00393     operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
00394     {
00395       reset(__u.release());
00396       get_deleter() = std::forward<_Ep>(__u.get_deleter());
00397       return *this;
00398     }
00399 
00400       unique_ptr&
00401       operator=(nullptr_t) noexcept
00402       {
00403     reset();
00404     return *this;
00405       }
00406 
00407       // Observers.
00408       typename std::add_lvalue_reference<element_type>::type
00409       operator[](size_t __i) const
00410       {
00411     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00412     return get()[__i];
00413       }
00414 
00415       pointer
00416       get() const noexcept
00417       { return std::get<0>(_M_t); }
00418 
00419       deleter_type&
00420       get_deleter() noexcept
00421       { return std::get<1>(_M_t); }
00422 
00423       const deleter_type&
00424       get_deleter() const noexcept
00425       { return std::get<1>(_M_t); }
00426 
00427       explicit operator bool() const noexcept
00428       { return get() == pointer() ? false : true; }
00429 
00430       // Modifiers.
00431       pointer
00432       release() noexcept
00433       {
00434     pointer __p = get();
00435     std::get<0>(_M_t) = pointer();
00436     return __p;
00437       }
00438 
00439       void
00440       reset() noexcept
00441       { reset(pointer()); }
00442 
00443       void
00444       reset(pointer __p) noexcept
00445       {
00446     using std::swap;
00447     swap(std::get<0>(_M_t), __p);
00448     if (__p != nullptr)
00449       get_deleter()(__p);
00450       }
00451 
00452       template<typename _Up, typename = _Require<is_pointer<pointer>,
00453            is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
00454     void reset(_Up*) = delete;
00455 
00456       void
00457       swap(unique_ptr& __u) noexcept
00458       {
00459     using std::swap;
00460     swap(_M_t, __u._M_t);
00461       }
00462 
00463       // Disable copy from lvalue.
00464       unique_ptr(const unique_ptr&) = delete;
00465       unique_ptr& operator=(const unique_ptr&) = delete;
00466 
00467       // Disable construction from convertible pointer types.
00468       template<typename _Up, typename = _Require<is_pointer<pointer>,
00469            is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
00470     unique_ptr(_Up*, typename
00471            conditional<is_reference<deleter_type>::value,
00472            deleter_type, const deleter_type&>::type) = delete;
00473 
00474       template<typename _Up, typename = _Require<is_pointer<pointer>,
00475            is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
00476     unique_ptr(_Up*, typename
00477            remove_reference<deleter_type>::type&&) = delete;
00478     };
00479 
00480   template<typename _Tp, typename _Dp>
00481     inline void
00482     swap(unique_ptr<_Tp, _Dp>& __x,
00483      unique_ptr<_Tp, _Dp>& __y) noexcept
00484     { __x.swap(__y); }
00485 
00486   template<typename _Tp, typename _Dp,
00487        typename _Up, typename _Ep>
00488     inline bool
00489     operator==(const unique_ptr<_Tp, _Dp>& __x,
00490            const unique_ptr<_Up, _Ep>& __y)
00491     { return __x.get() == __y.get(); }
00492 
00493   template<typename _Tp, typename _Dp>
00494     inline bool
00495     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
00496     { return !__x; }
00497 
00498   template<typename _Tp, typename _Dp>
00499     inline bool
00500     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
00501     { return !__x; }
00502 
00503   template<typename _Tp, typename _Dp,
00504        typename _Up, typename _Ep>
00505     inline bool
00506     operator!=(const unique_ptr<_Tp, _Dp>& __x,
00507            const unique_ptr<_Up, _Ep>& __y)
00508     { return __x.get() != __y.get(); }
00509 
00510   template<typename _Tp, typename _Dp>
00511     inline bool
00512     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
00513     { return (bool)__x; }
00514 
00515   template<typename _Tp, typename _Dp>
00516     inline bool
00517     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
00518     { return (bool)__x; }
00519 
00520   template<typename _Tp, typename _Dp,
00521        typename _Up, typename _Ep>
00522     inline bool
00523     operator<(const unique_ptr<_Tp, _Dp>& __x,
00524           const unique_ptr<_Up, _Ep>& __y)
00525     {
00526       typedef typename
00527     std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
00528                      typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
00529       return std::less<_CT>()(__x.get(), __y.get());
00530     }
00531 
00532   template<typename _Tp, typename _Dp>
00533     inline bool
00534     operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00535     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
00536                                  nullptr); }
00537 
00538   template<typename _Tp, typename _Dp>
00539     inline bool
00540     operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00541     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
00542                                  __x.get()); }
00543 
00544   template<typename _Tp, typename _Dp,
00545        typename _Up, typename _Ep>
00546     inline bool
00547     operator<=(const unique_ptr<_Tp, _Dp>& __x,
00548            const unique_ptr<_Up, _Ep>& __y)
00549     { return !(__y < __x); }
00550 
00551   template<typename _Tp, typename _Dp>
00552     inline bool
00553     operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00554     { return !(nullptr < __x); }
00555 
00556   template<typename _Tp, typename _Dp>
00557     inline bool
00558     operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00559     { return !(__x < nullptr); }
00560 
00561   template<typename _Tp, typename _Dp,
00562        typename _Up, typename _Ep>
00563     inline bool
00564     operator>(const unique_ptr<_Tp, _Dp>& __x,
00565           const unique_ptr<_Up, _Ep>& __y)
00566     { return (__y < __x); }
00567 
00568   template<typename _Tp, typename _Dp>
00569     inline bool
00570     operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00571     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
00572                                  __x.get()); }
00573 
00574   template<typename _Tp, typename _Dp>
00575     inline bool
00576     operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00577     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
00578                                  nullptr); }
00579 
00580   template<typename _Tp, typename _Dp,
00581        typename _Up, typename _Ep>
00582     inline bool
00583     operator>=(const unique_ptr<_Tp, _Dp>& __x,
00584            const unique_ptr<_Up, _Ep>& __y)
00585     { return !(__x < __y); }
00586 
00587   template<typename _Tp, typename _Dp>
00588     inline bool
00589     operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00590     { return !(__x < nullptr); }
00591 
00592   template<typename _Tp, typename _Dp>
00593     inline bool
00594     operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00595     { return !(nullptr < __x); }
00596 
00597   /// std::hash specialization for unique_ptr.
00598   template<typename _Tp, typename _Dp>
00599     struct hash<unique_ptr<_Tp, _Dp>>
00600     : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
00601     {
00602       size_t
00603       operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
00604       {
00605     typedef unique_ptr<_Tp, _Dp> _UP;
00606     return std::hash<typename _UP::pointer>()(__u.get());
00607       }
00608     };
00609 
00610   // @} group pointer_abstractions
00611 
00612 _GLIBCXX_END_NAMESPACE_VERSION
00613 } // namespace
00614 
00615 #endif /* _UNIQUE_PTR_H */