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