Home | History | Annotate | Download | only in bits
      1 // unique_ptr implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2008-2013 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file bits/unique_ptr.h
     26  *  This is an internal header file, included by other library headers.
     27  *  Do not attempt to use it directly. @headername{memory}
     28  */
     29 
     30 #ifndef _UNIQUE_PTR_H
     31 #define _UNIQUE_PTR_H 1
     32 
     33 #include <bits/c++config.h>
     34 #include <debug/debug.h>
     35 #include <type_traits>
     36 #include <utility>
     37 #include <tuple>
     38 
     39 namespace std _GLIBCXX_VISIBILITY(default)
     40 {
     41 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     42 
     43   /**
     44    * @addtogroup pointer_abstractions
     45    * @{
     46    */
     47 
     48 #if _GLIBCXX_USE_DEPRECATED
     49   template<typename> class auto_ptr;
     50 #endif
     51 
     52   /// Primary template, default_delete.
     53   template<typename _Tp>
     54     struct default_delete
     55     {
     56       constexpr default_delete() noexcept = default;
     57 
     58       template<typename _Up, typename = typename
     59 	       enable_if<is_convertible<_Up*, _Tp*>::value>::type>
     60         default_delete(const default_delete<_Up>&) noexcept { }
     61 
     62       void
     63       operator()(_Tp* __ptr) const
     64       {
     65 	static_assert(sizeof(_Tp)>0,
     66 		      "can't delete pointer to incomplete type");
     67 	delete __ptr;
     68       }
     69     };
     70 
     71   // _GLIBCXX_RESOLVE_LIB_DEFECTS
     72   // DR 740 - omit specialization for array objects with a compile time length
     73   /// Specialization, default_delete.
     74   template<typename _Tp>
     75     struct default_delete<_Tp[]>
     76     {
     77     private:
     78       template<typename _Up>
     79 	using __remove_cv = typename remove_cv<_Up>::type;
     80 
     81       // Like is_base_of<_Tp, _Up> but false if unqualified types are the same
     82       template<typename _Up>
     83 	using __is_derived_Tp
     84 	  = __and_< is_base_of<_Tp, _Up>,
     85 		    __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
     86 
     87     public:
     88       constexpr default_delete() noexcept = default;
     89 
     90       template<typename _Up, typename = typename
     91 	       enable_if<!__is_derived_Tp<_Up>::value>::type>
     92         default_delete(const default_delete<_Up[]>&) noexcept { }
     93 
     94       void
     95       operator()(_Tp* __ptr) const
     96       {
     97 	static_assert(sizeof(_Tp)>0,
     98 		      "can't delete pointer to incomplete type");
     99 	delete [] __ptr;
    100       }
    101 
    102       template<typename _Up>
    103 	typename enable_if<__is_derived_Tp<_Up>::value>::type
    104 	operator()(_Up*) const = delete;
    105     };
    106 
    107   /// 20.7.1.2 unique_ptr for single objects.
    108   template <typename _Tp, typename _Dp = default_delete<_Tp> >
    109     class unique_ptr
    110     {
    111       // use SFINAE to determine whether _Del::pointer exists
    112       class _Pointer
    113       {
    114 	template<typename _Up>
    115 	  static typename _Up::pointer __test(typename _Up::pointer*);
    116 
    117 	template<typename _Up>
    118 	  static _Tp* __test(...);
    119 
    120 	typedef typename remove_reference<_Dp>::type _Del;
    121 
    122       public:
    123 	typedef decltype(__test<_Del>(0)) type;
    124       };
    125 
    126       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
    127       __tuple_type                                      _M_t;
    128 
    129     public:
    130       typedef typename _Pointer::type   pointer;
    131       typedef _Tp                       element_type;
    132       typedef _Dp                       deleter_type;
    133 
    134       // Constructors.
    135       constexpr unique_ptr() noexcept
    136       : _M_t()
    137       { static_assert(!is_pointer<deleter_type>::value,
    138 		     "constructed with null function pointer deleter"); }
    139 
    140       explicit
    141       unique_ptr(pointer __p) noexcept
    142       : _M_t(__p, deleter_type())
    143       { static_assert(!is_pointer<deleter_type>::value,
    144 		     "constructed with null function pointer deleter"); }
    145 
    146       unique_ptr(pointer __p,
    147 	  typename conditional<is_reference<deleter_type>::value,
    148 	    deleter_type, const deleter_type&>::type __d) noexcept
    149       : _M_t(__p, __d) { }
    150 
    151       unique_ptr(pointer __p,
    152 	  typename remove_reference<deleter_type>::type&& __d) noexcept
    153       : _M_t(std::move(__p), std::move(__d))
    154       { static_assert(!std::is_reference<deleter_type>::value,
    155 		      "rvalue deleter bound to reference"); }
    156 
    157       constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
    158 
    159       // Move constructors.
    160       unique_ptr(unique_ptr&& __u) noexcept
    161       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
    162 
    163       template<typename _Up, typename _Ep, typename = _Require<
    164 	       is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
    165 	       __not_<is_array<_Up>>,
    166 	       typename conditional<is_reference<_Dp>::value,
    167 				    is_same<_Ep, _Dp>,
    168 				    is_convertible<_Ep, _Dp>>::type>>
    169 	unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
    170 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
    171 	{ }
    172 
    173 #if _GLIBCXX_USE_DEPRECATED
    174       template<typename _Up, typename = _Require<
    175 	       is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
    176 	unique_ptr(auto_ptr<_Up>&& __u) noexcept;
    177 #endif
    178 
    179       // Destructor.
    180       ~unique_ptr() noexcept
    181       {
    182 	auto& __ptr = std::get<0>(_M_t);
    183 	if (__ptr != nullptr)
    184 	  get_deleter()(__ptr);
    185 	__ptr = pointer();
    186       }
    187 
    188       // Assignment.
    189       unique_ptr&
    190       operator=(unique_ptr&& __u) noexcept
    191       {
    192 	reset(__u.release());
    193 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
    194 	return *this;
    195       }
    196 
    197       template<typename _Up, typename _Ep>
    198 	typename enable_if< __and_<
    199 	  is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
    200 	  __not_<is_array<_Up>>
    201 	  >::value,
    202 	  unique_ptr&>::type
    203 	operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
    204 	{
    205 	  reset(__u.release());
    206 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
    207 	  return *this;
    208 	}
    209 
    210       unique_ptr&
    211       operator=(nullptr_t) noexcept
    212       {
    213 	reset();
    214 	return *this;
    215       }
    216 
    217       // Observers.
    218       typename add_lvalue_reference<element_type>::type
    219       operator*() const
    220       {
    221 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    222 	return *get();
    223       }
    224 
    225       pointer
    226       operator->() const noexcept
    227       {
    228 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    229 	return get();
    230       }
    231 
    232       pointer
    233       get() const noexcept
    234       { return std::get<0>(_M_t); }
    235 
    236       deleter_type&
    237       get_deleter() noexcept
    238       { return std::get<1>(_M_t); }
    239 
    240       const deleter_type&
    241       get_deleter() const noexcept
    242       { return std::get<1>(_M_t); }
    243 
    244       explicit operator bool() const noexcept
    245       { return get() == pointer() ? false : true; }
    246 
    247       // Modifiers.
    248       pointer
    249       release() noexcept
    250       {
    251 	pointer __p = get();
    252 	std::get<0>(_M_t) = pointer();
    253 	return __p;
    254       }
    255 
    256       void
    257       reset(pointer __p = pointer()) noexcept
    258       {
    259 	using std::swap;
    260 	swap(std::get<0>(_M_t), __p);
    261 	if (__p != pointer())
    262 	  get_deleter()(__p);
    263       }
    264 
    265       void
    266       swap(unique_ptr& __u) noexcept
    267       {
    268 	using std::swap;
    269 	swap(_M_t, __u._M_t);
    270       }
    271 
    272       // Disable copy from lvalue.
    273       unique_ptr(const unique_ptr&) = delete;
    274       unique_ptr& operator=(const unique_ptr&) = delete;
    275   };
    276 
    277   /// 20.7.1.3 unique_ptr for array objects with a runtime length
    278   // [unique.ptr.runtime]
    279   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    280   // DR 740 - omit specialization for array objects with a compile time length
    281   template<typename _Tp, typename _Dp>
    282     class unique_ptr<_Tp[], _Dp>
    283     {
    284       // use SFINAE to determine whether _Del::pointer exists
    285       class _Pointer
    286       {
    287 	template<typename _Up>
    288 	  static typename _Up::pointer __test(typename _Up::pointer*);
    289 
    290 	template<typename _Up>
    291 	  static _Tp* __test(...);
    292 
    293 	typedef typename remove_reference<_Dp>::type _Del;
    294 
    295       public:
    296 	typedef decltype(__test<_Del>(0)) type;
    297       };
    298 
    299       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
    300       __tuple_type                                      _M_t;
    301 
    302       template<typename _Up>
    303 	using __remove_cv = typename remove_cv<_Up>::type;
    304 
    305       // like is_base_of<_Tp, _Up> but false if unqualified types are the same
    306       template<typename _Up>
    307 	using __is_derived_Tp
    308 	  = __and_< is_base_of<_Tp, _Up>,
    309 		    __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
    310 
    311       template<typename _Up, typename _Ep,
    312 	       typename _Tp_pointer = typename _Pointer::type,
    313 	       typename _Up_pointer = typename unique_ptr<_Up, _Ep>::pointer>
    314 	using __safe_conversion = __and_<
    315 	    is_convertible<_Up_pointer, _Tp_pointer>,
    316 	    is_array<_Up>,
    317 	    __or_<__not_<is_pointer<_Up_pointer>>,
    318 		  __not_<is_pointer<_Tp_pointer>>,
    319 		  __not_<__is_derived_Tp<typename remove_extent<_Up>::type>>
    320 	    >
    321 	  >;
    322 
    323     public:
    324       typedef typename _Pointer::type	pointer;
    325       typedef _Tp		 	element_type;
    326       typedef _Dp                       deleter_type;
    327 
    328       // Constructors.
    329       constexpr unique_ptr() noexcept
    330       : _M_t()
    331       { static_assert(!std::is_pointer<deleter_type>::value,
    332 		      "constructed with null function pointer deleter"); }
    333 
    334       explicit
    335       unique_ptr(pointer __p) noexcept
    336       : _M_t(__p, deleter_type())
    337       { static_assert(!is_pointer<deleter_type>::value,
    338 		      "constructed with null function pointer deleter"); }
    339 
    340       template<typename _Up, typename = _Require<is_pointer<pointer>,
    341 	       is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
    342 	explicit
    343 	unique_ptr(_Up* __p) = delete;
    344 
    345       unique_ptr(pointer __p,
    346 	  typename conditional<is_reference<deleter_type>::value,
    347 	      deleter_type, const deleter_type&>::type __d) noexcept
    348       : _M_t(__p, __d) { }
    349 
    350       unique_ptr(pointer __p, typename
    351 		 remove_reference<deleter_type>::type&& __d) noexcept
    352       : _M_t(std::move(__p), std::move(__d))
    353       { static_assert(!is_reference<deleter_type>::value,
    354 		      "rvalue deleter bound to reference"); }
    355 
    356       // Move constructor.
    357       unique_ptr(unique_ptr&& __u) noexcept
    358       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
    359 
    360       constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
    361 
    362       template<typename _Up, typename _Ep,
    363 	       typename = _Require<__safe_conversion<_Up, _Ep>,
    364 		 typename conditional<is_reference<_Dp>::value,
    365 				      is_same<_Ep, _Dp>,
    366 				      is_convertible<_Ep, _Dp>>::type
    367 	       >>
    368 	unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
    369 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
    370 	{ }
    371 
    372       // Destructor.
    373       ~unique_ptr()
    374       {
    375 	auto& __ptr = std::get<0>(_M_t);
    376 	if (__ptr != nullptr)
    377 	  get_deleter()(__ptr);
    378 	__ptr = pointer();
    379       }
    380 
    381       // Assignment.
    382       unique_ptr&
    383       operator=(unique_ptr&& __u) noexcept
    384       {
    385 	reset(__u.release());
    386 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
    387 	return *this;
    388       }
    389 
    390       template<typename _Up, typename _Ep>
    391 	typename
    392 	enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type
    393 	operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
    394 	{
    395 	  reset(__u.release());
    396 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
    397 	  return *this;
    398 	}
    399 
    400       unique_ptr&
    401       operator=(nullptr_t) noexcept
    402       {
    403 	reset();
    404 	return *this;
    405       }
    406 
    407       // Observers.
    408       typename std::add_lvalue_reference<element_type>::type
    409       operator[](size_t __i) const
    410       {
    411 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    412 	return get()[__i];
    413       }
    414 
    415       pointer
    416       get() const noexcept
    417       { return std::get<0>(_M_t); }
    418 
    419       deleter_type&
    420       get_deleter() noexcept
    421       { return std::get<1>(_M_t); }
    422 
    423       const deleter_type&
    424       get_deleter() const noexcept
    425       { return std::get<1>(_M_t); }
    426 
    427       explicit operator bool() const noexcept
    428       { return get() == pointer() ? false : true; }
    429 
    430       // Modifiers.
    431       pointer
    432       release() noexcept
    433       {
    434 	pointer __p = get();
    435 	std::get<0>(_M_t) = pointer();
    436 	return __p;
    437       }
    438 
    439       void
    440       reset() noexcept
    441       { reset(pointer()); }
    442 
    443       void
    444       reset(pointer __p) noexcept
    445       {
    446 	using std::swap;
    447 	swap(std::get<0>(_M_t), __p);
    448 	if (__p != nullptr)
    449 	  get_deleter()(__p);
    450       }
    451 
    452       template<typename _Up, typename = _Require<is_pointer<pointer>,
    453 	       is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
    454 	void reset(_Up*) = delete;
    455 
    456       void
    457       swap(unique_ptr& __u) noexcept
    458       {
    459 	using std::swap;
    460 	swap(_M_t, __u._M_t);
    461       }
    462 
    463       // Disable copy from lvalue.
    464       unique_ptr(const unique_ptr&) = delete;
    465       unique_ptr& operator=(const unique_ptr&) = delete;
    466 
    467       // Disable construction from convertible pointer types.
    468       template<typename _Up, typename = _Require<is_pointer<pointer>,
    469 	       is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
    470 	unique_ptr(_Up*, typename
    471 		   conditional<is_reference<deleter_type>::value,
    472 		   deleter_type, const deleter_type&>::type) = delete;
    473 
    474       template<typename _Up, typename = _Require<is_pointer<pointer>,
    475 	       is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
    476 	unique_ptr(_Up*, typename
    477 		   remove_reference<deleter_type>::type&&) = delete;
    478     };
    479 
    480   template<typename _Tp, typename _Dp>
    481     inline void
    482     swap(unique_ptr<_Tp, _Dp>& __x,
    483 	 unique_ptr<_Tp, _Dp>& __y) noexcept
    484     { __x.swap(__y); }
    485 
    486   template<typename _Tp, typename _Dp,
    487 	   typename _Up, typename _Ep>
    488     inline bool
    489     operator==(const unique_ptr<_Tp, _Dp>& __x,
    490 	       const unique_ptr<_Up, _Ep>& __y)
    491     { return __x.get() == __y.get(); }
    492 
    493   template<typename _Tp, typename _Dp>
    494     inline bool
    495     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
    496     { return !__x; }
    497 
    498   template<typename _Tp, typename _Dp>
    499     inline bool
    500     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
    501     { return !__x; }
    502 
    503   template<typename _Tp, typename _Dp,
    504 	   typename _Up, typename _Ep>
    505     inline bool
    506     operator!=(const unique_ptr<_Tp, _Dp>& __x,
    507 	       const unique_ptr<_Up, _Ep>& __y)
    508     { return __x.get() != __y.get(); }
    509 
    510   template<typename _Tp, typename _Dp>
    511     inline bool
    512     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
    513     { return (bool)__x; }
    514 
    515   template<typename _Tp, typename _Dp>
    516     inline bool
    517     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
    518     { return (bool)__x; }
    519 
    520   template<typename _Tp, typename _Dp,
    521 	   typename _Up, typename _Ep>
    522     inline bool
    523     operator<(const unique_ptr<_Tp, _Dp>& __x,
    524 	      const unique_ptr<_Up, _Ep>& __y)
    525     {
    526       typedef typename
    527 	std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
    528 	                 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
    529       return std::less<_CT>()(__x.get(), __y.get());
    530     }
    531 
    532   template<typename _Tp, typename _Dp>
    533     inline bool
    534     operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    535     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
    536 								 nullptr); }
    537 
    538   template<typename _Tp, typename _Dp>
    539     inline bool
    540     operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    541     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
    542 								 __x.get()); }
    543 
    544   template<typename _Tp, typename _Dp,
    545 	   typename _Up, typename _Ep>
    546     inline bool
    547     operator<=(const unique_ptr<_Tp, _Dp>& __x,
    548 	       const unique_ptr<_Up, _Ep>& __y)
    549     { return !(__y < __x); }
    550 
    551   template<typename _Tp, typename _Dp>
    552     inline bool
    553     operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    554     { return !(nullptr < __x); }
    555 
    556   template<typename _Tp, typename _Dp>
    557     inline bool
    558     operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    559     { return !(__x < nullptr); }
    560 
    561   template<typename _Tp, typename _Dp,
    562 	   typename _Up, typename _Ep>
    563     inline bool
    564     operator>(const unique_ptr<_Tp, _Dp>& __x,
    565 	      const unique_ptr<_Up, _Ep>& __y)
    566     { return (__y < __x); }
    567 
    568   template<typename _Tp, typename _Dp>
    569     inline bool
    570     operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    571     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
    572 								 __x.get()); }
    573 
    574   template<typename _Tp, typename _Dp>
    575     inline bool
    576     operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    577     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
    578 								 nullptr); }
    579 
    580   template<typename _Tp, typename _Dp,
    581 	   typename _Up, typename _Ep>
    582     inline bool
    583     operator>=(const unique_ptr<_Tp, _Dp>& __x,
    584 	       const unique_ptr<_Up, _Ep>& __y)
    585     { return !(__x < __y); }
    586 
    587   template<typename _Tp, typename _Dp>
    588     inline bool
    589     operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    590     { return !(__x < nullptr); }
    591 
    592   template<typename _Tp, typename _Dp>
    593     inline bool
    594     operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    595     { return !(nullptr < __x); }
    596 
    597   /// std::hash specialization for unique_ptr.
    598   template<typename _Tp, typename _Dp>
    599     struct hash<unique_ptr<_Tp, _Dp>>
    600     : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
    601     {
    602       size_t
    603       operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
    604       {
    605 	typedef unique_ptr<_Tp, _Dp> _UP;
    606 	return std::hash<typename _UP::pointer>()(__u.get());
    607       }
    608     };
    609 
    610   // @} group pointer_abstractions
    611 
    612 _GLIBCXX_END_NAMESPACE_VERSION
    613 } // namespace
    614 
    615 #endif /* _UNIQUE_PTR_H */
    616