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