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 { reset(); }
00170 
00171       // Assignment.
00172       unique_ptr&
00173       operator=(unique_ptr&& __u) noexcept
00174       {
00175     reset(__u.release());
00176     get_deleter() = std::forward<deleter_type>(__u.get_deleter());
00177     return *this;
00178       }
00179 
00180       template<typename _Up, typename _Ep, typename = typename
00181     std::enable_if
00182       <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
00183                    pointer>::value
00184        && !std::is_array<_Up>::value>::type>
00185     unique_ptr&
00186     operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
00187     {
00188       reset(__u.release());
00189       get_deleter() = std::forward<_Ep>(__u.get_deleter());
00190       return *this;
00191     }
00192 
00193       unique_ptr&
00194       operator=(nullptr_t) noexcept
00195       {
00196     reset();
00197     return *this;
00198       }
00199 
00200       // Observers.
00201       typename std::add_lvalue_reference<element_type>::type
00202       operator*() const
00203       {
00204     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00205     return *get();
00206       }
00207 
00208       pointer
00209       operator->() const noexcept
00210       {
00211     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00212     return get();
00213       }
00214 
00215       pointer
00216       get() const noexcept
00217       { return std::get<0>(_M_t); }
00218 
00219       deleter_type&
00220       get_deleter() noexcept
00221       { return std::get<1>(_M_t); }
00222 
00223       const deleter_type&
00224       get_deleter() const noexcept
00225       { return std::get<1>(_M_t); }
00226 
00227       explicit operator bool() const noexcept
00228       { return get() == pointer() ? false : true; }
00229 
00230       // Modifiers.
00231       pointer
00232       release() noexcept
00233       {
00234     pointer __p = get();
00235     std::get<0>(_M_t) = pointer();
00236     return __p;
00237       }
00238 
00239       void
00240       reset(pointer __p = pointer()) noexcept
00241       {
00242     using std::swap;
00243     swap(std::get<0>(_M_t), __p);
00244     if (__p != pointer())
00245       get_deleter()(__p);
00246       }
00247 
00248       void
00249       swap(unique_ptr& __u) noexcept
00250       {
00251     using std::swap;
00252     swap(_M_t, __u._M_t);
00253       }
00254 
00255       // Disable copy from lvalue.
00256       unique_ptr(const unique_ptr&) = delete;
00257       unique_ptr& operator=(const unique_ptr&) = delete;
00258   };
00259 
00260   /// 20.7.12.3 unique_ptr for array objects with a runtime length
00261   // [unique.ptr.runtime]
00262   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00263   // DR 740 - omit specialization for array objects with a compile time length
00264   template<typename _Tp, typename _Dp>
00265     class unique_ptr<_Tp[], _Dp>
00266     {
00267       typedef std::tuple<_Tp*, _Dp>     __tuple_type;
00268       __tuple_type          _M_t;
00269 
00270     public:
00271       typedef _Tp*          pointer;
00272       typedef _Tp           element_type;
00273       typedef _Dp                       deleter_type;
00274 
00275       // Constructors.
00276       constexpr unique_ptr() noexcept
00277       : _M_t()
00278       { static_assert(!std::is_pointer<deleter_type>::value,
00279              "constructed with null function pointer deleter"); }
00280 
00281       explicit
00282       unique_ptr(pointer __p) noexcept
00283       : _M_t(__p, deleter_type())
00284       { static_assert(!std::is_pointer<deleter_type>::value,
00285              "constructed with null function pointer deleter"); }
00286 
00287       unique_ptr(pointer __p,
00288       typename std::conditional<std::is_reference<deleter_type>::value,
00289           deleter_type, const deleter_type&>::type __d) noexcept
00290       : _M_t(__p, __d) { }
00291 
00292       unique_ptr(pointer __p, typename
00293          std::remove_reference<deleter_type>::type && __d) noexcept
00294       : _M_t(std::move(__p), std::move(__d))
00295       { static_assert(!std::is_reference<deleter_type>::value,
00296               "rvalue deleter bound to reference"); }
00297 
00298       constexpr unique_ptr(nullptr_t) noexcept
00299       : _M_t()
00300       { static_assert(!std::is_pointer<deleter_type>::value,
00301              "constructed with null function pointer deleter"); }
00302 
00303       // Move constructors.
00304       unique_ptr(unique_ptr&& __u) noexcept
00305       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00306 
00307       template<typename _Up, typename _Ep>
00308     unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
00309     : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
00310     { }
00311 
00312       // Destructor.
00313       ~unique_ptr() { reset(); }
00314 
00315       // Assignment.
00316       unique_ptr&
00317       operator=(unique_ptr&& __u) noexcept
00318       {
00319     reset(__u.release());
00320     get_deleter() = std::forward<deleter_type>(__u.get_deleter());
00321     return *this;
00322       }
00323 
00324       template<typename _Up, typename _Ep>
00325     unique_ptr&
00326     operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
00327     {
00328       reset(__u.release());
00329       get_deleter() = std::forward<_Ep>(__u.get_deleter());
00330       return *this;
00331     }
00332 
00333       unique_ptr&
00334       operator=(nullptr_t) noexcept
00335       {
00336     reset();
00337     return *this;
00338       }
00339 
00340       // Observers.
00341       typename std::add_lvalue_reference<element_type>::type
00342       operator[](size_t __i) const
00343       {
00344     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00345     return get()[__i];
00346       }
00347 
00348       pointer
00349       get() const noexcept
00350       { return std::get<0>(_M_t); }
00351 
00352       deleter_type&
00353       get_deleter() noexcept
00354       { return std::get<1>(_M_t); }
00355 
00356       const deleter_type&
00357       get_deleter() const noexcept
00358       { return std::get<1>(_M_t); }
00359 
00360       explicit operator bool() const noexcept
00361       { return get() == pointer() ? false : true; }
00362 
00363       // Modifiers.
00364       pointer
00365       release() noexcept
00366       {
00367     pointer __p = get();
00368     std::get<0>(_M_t) = pointer();
00369     return __p;
00370       }
00371 
00372       void
00373       reset(pointer __p = pointer()) noexcept
00374       {
00375     using std::swap;
00376     swap(std::get<0>(_M_t), __p);
00377     if (__p != nullptr)
00378       get_deleter()(__p);
00379       }
00380 
00381       void
00382       reset(nullptr_t) noexcept
00383       {
00384     pointer __p = get();
00385     std::get<0>(_M_t) = pointer();
00386     if (__p != nullptr)
00387       get_deleter()(__p);
00388       }
00389 
00390       // DR 821.
00391       template<typename _Up>
00392     void reset(_Up) = delete;
00393 
00394       void
00395       swap(unique_ptr& __u) noexcept
00396       {
00397     using std::swap;
00398     swap(_M_t, __u._M_t);
00399       }
00400 
00401       // Disable copy from lvalue.
00402       unique_ptr(const unique_ptr&) = delete;
00403       unique_ptr& operator=(const unique_ptr&) = delete;
00404 
00405       // Disable construction from convertible pointer types.
00406       // (N2315 - 20.6.5.3.1)
00407       template<typename _Up>
00408     unique_ptr(_Up*, typename
00409            std::conditional<std::is_reference<deleter_type>::value,
00410            deleter_type, const deleter_type&>::type,
00411            typename std::enable_if<std::is_convertible<_Up*,
00412            pointer>::value>::type* = 0) = delete;
00413 
00414       template<typename _Up>
00415     unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
00416            typename std::enable_if<std::is_convertible<_Up*,
00417            pointer>::value>::type* = 0) = delete;
00418 
00419       template<typename _Up>
00420     explicit
00421     unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
00422            pointer>::value>::type* = 0) = delete;
00423     };
00424 
00425   template<typename _Tp, typename _Dp>
00426     inline void
00427     swap(unique_ptr<_Tp, _Dp>& __x,
00428      unique_ptr<_Tp, _Dp>& __y) noexcept
00429     { __x.swap(__y); }
00430 
00431   template<typename _Tp, typename _Dp,
00432        typename _Up, typename _Ep>
00433     inline bool
00434     operator==(const unique_ptr<_Tp, _Dp>& __x,
00435            const unique_ptr<_Up, _Ep>& __y)
00436     { return __x.get() == __y.get(); }
00437 
00438   template<typename _Tp, typename _Dp>
00439     inline bool
00440     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
00441     { return !__x; }
00442 
00443   template<typename _Tp, typename _Dp>
00444     inline bool
00445     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
00446     { return !__x; }
00447 
00448   template<typename _Tp, typename _Dp,
00449        typename _Up, typename _Ep>
00450     inline bool
00451     operator!=(const unique_ptr<_Tp, _Dp>& __x,
00452            const unique_ptr<_Up, _Ep>& __y)
00453     { return __x.get() != __y.get(); }
00454 
00455   template<typename _Tp, typename _Dp>
00456     inline bool
00457     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
00458     { return (bool)__x; }
00459 
00460   template<typename _Tp, typename _Dp>
00461     inline bool
00462     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
00463     { return (bool)__x; }
00464 
00465   template<typename _Tp, typename _Dp,
00466        typename _Up, typename _Ep>
00467     inline bool
00468     operator<(const unique_ptr<_Tp, _Dp>& __x,
00469           const unique_ptr<_Up, _Ep>& __y)
00470     {
00471       typedef typename
00472     std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
00473                      typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
00474       return std::less<_CT>()(__x.get(), __y.get());
00475     }
00476 
00477   template<typename _Tp, typename _Dp>
00478     inline bool
00479     operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00480     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
00481                                  nullptr); }
00482 
00483   template<typename _Tp, typename _Dp>
00484     inline bool
00485     operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00486     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
00487                                  __x.get()); }
00488 
00489   template<typename _Tp, typename _Dp,
00490        typename _Up, typename _Ep>
00491     inline bool
00492     operator<=(const unique_ptr<_Tp, _Dp>& __x,
00493            const unique_ptr<_Up, _Ep>& __y)
00494     { return !(__y < __x); }
00495 
00496   template<typename _Tp, typename _Dp>
00497     inline bool
00498     operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00499     { return !(nullptr < __x); }
00500 
00501   template<typename _Tp, typename _Dp>
00502     inline bool
00503     operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00504     { return !(__x < nullptr); }
00505 
00506   template<typename _Tp, typename _Dp,
00507        typename _Up, typename _Ep>
00508     inline bool
00509     operator>(const unique_ptr<_Tp, _Dp>& __x,
00510           const unique_ptr<_Up, _Ep>& __y)
00511     { return (__y < __x); }
00512 
00513   template<typename _Tp, typename _Dp>
00514     inline bool
00515     operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00516     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
00517                                  __x.get()); }
00518 
00519   template<typename _Tp, typename _Dp>
00520     inline bool
00521     operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00522     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
00523                                  nullptr); }
00524 
00525   template<typename _Tp, typename _Dp,
00526        typename _Up, typename _Ep>
00527     inline bool
00528     operator>=(const unique_ptr<_Tp, _Dp>& __x,
00529            const unique_ptr<_Up, _Ep>& __y)
00530     { return !(__x < __y); }
00531 
00532   template<typename _Tp, typename _Dp>
00533     inline bool
00534     operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00535     { return !(__x < nullptr); }
00536 
00537   template<typename _Tp, typename _Dp>
00538     inline bool
00539     operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
00540     { return !(nullptr < __x); }
00541 
00542   /// std::hash specialization for unique_ptr.
00543   template<typename _Tp, typename _Dp>
00544     struct hash<unique_ptr<_Tp, _Dp>>
00545     : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
00546     {
00547       size_t
00548       operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
00549       {
00550     typedef unique_ptr<_Tp, _Dp> _UP;
00551     return std::hash<typename _UP::pointer>()(__u.get());
00552       }
00553     };
00554 
00555   // @} group pointer_abstractions
00556 
00557 _GLIBCXX_END_NAMESPACE_VERSION
00558 } // namespace
00559 
00560 #endif /* _UNIQUE_PTR_H */