Home | History | Annotate | Download | only in bits
      1 // unique_ptr implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2008, 2009, 2010, 2011 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   /// Primary template, default_delete.
     49   template<typename _Tp>
     50     struct default_delete
     51     {
     52       constexpr default_delete() noexcept = default;
     53 
     54       template<typename _Up, typename = typename
     55 	       std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type>
     56         default_delete(const default_delete<_Up>&) noexcept { }
     57 
     58       void
     59       operator()(_Tp* __ptr) const
     60       {
     61 	static_assert(sizeof(_Tp)>0,
     62 		      "can't delete pointer to incomplete type");
     63 	delete __ptr;
     64       }
     65     };
     66 
     67   // _GLIBCXX_RESOLVE_LIB_DEFECTS
     68   // DR 740 - omit specialization for array objects with a compile time length
     69   /// Specialization, default_delete.
     70   template<typename _Tp>
     71     struct default_delete<_Tp[]>
     72     {
     73       constexpr default_delete() noexcept = default;
     74 
     75       void
     76       operator()(_Tp* __ptr) const
     77       {
     78 	static_assert(sizeof(_Tp)>0,
     79 		      "can't delete pointer to incomplete type");
     80 	delete [] __ptr;
     81       }
     82 
     83       template<typename _Up> void operator()(_Up*) const = delete;
     84     };
     85 
     86   /// 20.7.12.2 unique_ptr for single objects.
     87   template <typename _Tp, typename _Dp = default_delete<_Tp> >
     88     class unique_ptr
     89     {
     90       // use SFINAE to determine whether _Del::pointer exists
     91       class _Pointer
     92       {
     93 	template<typename _Up>
     94 	  static typename _Up::pointer __test(typename _Up::pointer*);
     95 
     96 	template<typename _Up>
     97 	  static _Tp* __test(...);
     98 
     99 	typedef typename remove_reference<_Dp>::type _Del;
    100 
    101       public:
    102 	typedef decltype( __test<_Del>(0)) type;
    103       };
    104 
    105       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
    106       __tuple_type                                      _M_t;
    107 
    108     public:
    109       typedef typename _Pointer::type   pointer;
    110       typedef _Tp                       element_type;
    111       typedef _Dp                       deleter_type;
    112 
    113       // Constructors.
    114       constexpr unique_ptr() noexcept
    115       : _M_t()
    116       { static_assert(!std::is_pointer<deleter_type>::value,
    117 		     "constructed with null function pointer deleter"); }
    118 
    119       explicit
    120       unique_ptr(pointer __p) noexcept
    121       : _M_t(__p, deleter_type())
    122       { static_assert(!std::is_pointer<deleter_type>::value,
    123 		     "constructed with null function pointer deleter"); }
    124 
    125       unique_ptr(pointer __p,
    126 	  typename std::conditional<std::is_reference<deleter_type>::value,
    127 	    deleter_type, const deleter_type&>::type __d) noexcept
    128       : _M_t(__p, __d) { }
    129 
    130       unique_ptr(pointer __p,
    131 	  typename std::remove_reference<deleter_type>::type&& __d) noexcept
    132       : _M_t(std::move(__p), std::move(__d))
    133       { static_assert(!std::is_reference<deleter_type>::value,
    134 		      "rvalue deleter bound to reference"); }
    135 
    136       constexpr unique_ptr(nullptr_t) noexcept
    137       : _M_t()
    138       { static_assert(!std::is_pointer<deleter_type>::value,
    139 		     "constructed with null function pointer deleter"); }
    140 
    141       // Move constructors.
    142       unique_ptr(unique_ptr&& __u) noexcept
    143       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
    144 
    145       template<typename _Up, typename _Ep, typename = typename
    146 	std::enable_if
    147 	  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
    148 			       pointer>::value
    149 	   && !std::is_array<_Up>::value
    150 	   && ((std::is_reference<_Dp>::value
    151 		&& std::is_same<_Ep, _Dp>::value)
    152 	       || (!std::is_reference<_Dp>::value
    153 		   && std::is_convertible<_Ep, _Dp>::value))>
    154 	     ::type>
    155 	unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
    156 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
    157 	{ }
    158 
    159 #if _GLIBCXX_USE_DEPRECATED
    160       template<typename _Up, typename = typename
    161 	std::enable_if<std::is_convertible<_Up*, _Tp*>::value
    162 		       && std::is_same<_Dp,
    163 				       default_delete<_Tp>>::value>::type>
    164 	unique_ptr(auto_ptr<_Up>&& __u) noexcept
    165 	: _M_t(__u.release(), deleter_type()) { }
    166 #endif
    167 
    168       // Destructor.
    169       ~unique_ptr() noexcept
    170       {
    171 	auto& __ptr = std::get<0>(_M_t);
    172 	if (__ptr != nullptr)
    173 	  get_deleter()(__ptr);
    174 	__ptr = pointer();
    175       }
    176 
    177       // Assignment.
    178       unique_ptr&
    179       operator=(unique_ptr&& __u) noexcept
    180       {
    181 	reset(__u.release());
    182 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
    183 	return *this;
    184       }
    185 
    186       template<typename _Up, typename _Ep, typename = typename
    187 	std::enable_if
    188 	  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
    189 			       pointer>::value
    190 	   && !std::is_array<_Up>::value>::type>
    191 	unique_ptr&
    192 	operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
    193 	{
    194 	  reset(__u.release());
    195 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
    196 	  return *this;
    197 	}
    198 
    199       unique_ptr&
    200       operator=(nullptr_t) noexcept
    201       {
    202 	reset();
    203 	return *this;
    204       }
    205 
    206       // Observers.
    207       typename std::add_lvalue_reference<element_type>::type
    208       operator*() const
    209       {
    210 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    211 	return *get();
    212       }
    213 
    214       pointer
    215       operator->() const noexcept
    216       {
    217 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    218 	return get();
    219       }
    220 
    221       pointer
    222       get() const noexcept
    223       { return std::get<0>(_M_t); }
    224 
    225       deleter_type&
    226       get_deleter() noexcept
    227       { return std::get<1>(_M_t); }
    228 
    229       const deleter_type&
    230       get_deleter() const noexcept
    231       { return std::get<1>(_M_t); }
    232 
    233       explicit operator bool() const noexcept
    234       { return get() == pointer() ? false : true; }
    235 
    236       // Modifiers.
    237       pointer
    238       release() noexcept
    239       {
    240 	pointer __p = get();
    241 	std::get<0>(_M_t) = pointer();
    242 	return __p;
    243       }
    244 
    245       void
    246       reset(pointer __p = pointer()) noexcept
    247       {
    248 	using std::swap;
    249 	swap(std::get<0>(_M_t), __p);
    250 	if (__p != pointer())
    251 	  get_deleter()(__p);
    252       }
    253 
    254       void
    255       swap(unique_ptr& __u) noexcept
    256       {
    257 	using std::swap;
    258 	swap(_M_t, __u._M_t);
    259       }
    260 
    261       // Disable copy from lvalue.
    262       unique_ptr(const unique_ptr&) = delete;
    263       unique_ptr& operator=(const unique_ptr&) = delete;
    264   };
    265 
    266   /// 20.7.12.3 unique_ptr for array objects with a runtime length
    267   // [unique.ptr.runtime]
    268   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    269   // DR 740 - omit specialization for array objects with a compile time length
    270   template<typename _Tp, typename _Dp>
    271     class unique_ptr<_Tp[], _Dp>
    272     {
    273       typedef std::tuple<_Tp*, _Dp>  	__tuple_type;
    274       __tuple_type 			_M_t;
    275 
    276     public:
    277       typedef _Tp*		 	pointer;
    278       typedef _Tp		 	element_type;
    279       typedef _Dp                       deleter_type;
    280 
    281       // Constructors.
    282       constexpr unique_ptr() noexcept
    283       : _M_t()
    284       { static_assert(!std::is_pointer<deleter_type>::value,
    285 		     "constructed with null function pointer deleter"); }
    286 
    287       explicit
    288       unique_ptr(pointer __p) noexcept
    289       : _M_t(__p, deleter_type())
    290       { static_assert(!std::is_pointer<deleter_type>::value,
    291 		     "constructed with null function pointer deleter"); }
    292 
    293       unique_ptr(pointer __p,
    294 	  typename std::conditional<std::is_reference<deleter_type>::value,
    295 	      deleter_type, const deleter_type&>::type __d) noexcept
    296       : _M_t(__p, __d) { }
    297 
    298       unique_ptr(pointer __p, typename
    299 		 std::remove_reference<deleter_type>::type && __d) noexcept
    300       : _M_t(std::move(__p), std::move(__d))
    301       { static_assert(!std::is_reference<deleter_type>::value,
    302 		      "rvalue deleter bound to reference"); }
    303 
    304       constexpr unique_ptr(nullptr_t) noexcept
    305       : _M_t()
    306       { static_assert(!std::is_pointer<deleter_type>::value,
    307 		     "constructed with null function pointer deleter"); }
    308 
    309       // Move constructors.
    310       unique_ptr(unique_ptr&& __u) noexcept
    311       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
    312 
    313       template<typename _Up, typename _Ep>
    314 	unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
    315 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
    316 	{ }
    317 
    318       // Destructor.
    319       ~unique_ptr()
    320       {
    321 	auto& __ptr = std::get<0>(_M_t);
    322 	if (__ptr != nullptr)
    323 	  get_deleter()(__ptr);
    324 	__ptr = pointer();
    325       }
    326 
    327       // Assignment.
    328       unique_ptr&
    329       operator=(unique_ptr&& __u) noexcept
    330       {
    331 	reset(__u.release());
    332 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
    333 	return *this;
    334       }
    335 
    336       template<typename _Up, typename _Ep>
    337 	unique_ptr&
    338 	operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
    339 	{
    340 	  reset(__u.release());
    341 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
    342 	  return *this;
    343 	}
    344 
    345       unique_ptr&
    346       operator=(nullptr_t) noexcept
    347       {
    348 	reset();
    349 	return *this;
    350       }
    351 
    352       // Observers.
    353       typename std::add_lvalue_reference<element_type>::type
    354       operator[](size_t __i) const
    355       {
    356 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    357 	return get()[__i];
    358       }
    359 
    360       pointer
    361       get() const noexcept
    362       { return std::get<0>(_M_t); }
    363 
    364       deleter_type&
    365       get_deleter() noexcept
    366       { return std::get<1>(_M_t); }
    367 
    368       const deleter_type&
    369       get_deleter() const noexcept
    370       { return std::get<1>(_M_t); }
    371 
    372       explicit operator bool() const noexcept
    373       { return get() == pointer() ? false : true; }
    374 
    375       // Modifiers.
    376       pointer
    377       release() noexcept
    378       {
    379 	pointer __p = get();
    380 	std::get<0>(_M_t) = pointer();
    381 	return __p;
    382       }
    383 
    384       void
    385       reset(pointer __p = pointer()) noexcept
    386       {
    387 	using std::swap;
    388 	swap(std::get<0>(_M_t), __p);
    389 	if (__p != nullptr)
    390 	  get_deleter()(__p);
    391       }
    392 
    393       void
    394       reset(nullptr_t) noexcept
    395       {
    396 	pointer __p = get();
    397 	std::get<0>(_M_t) = pointer();
    398 	if (__p != nullptr)
    399 	  get_deleter()(__p);
    400       }
    401 
    402       // DR 821.
    403       template<typename _Up>
    404 	void reset(_Up) = delete;
    405 
    406       void
    407       swap(unique_ptr& __u) noexcept
    408       {
    409 	using std::swap;
    410 	swap(_M_t, __u._M_t);
    411       }
    412 
    413       // Disable copy from lvalue.
    414       unique_ptr(const unique_ptr&) = delete;
    415       unique_ptr& operator=(const unique_ptr&) = delete;
    416 
    417       // Disable construction from convertible pointer types.
    418       // (N2315 - 20.6.5.3.1)
    419       template<typename _Up>
    420 	unique_ptr(_Up*, typename
    421 		   std::conditional<std::is_reference<deleter_type>::value,
    422 		   deleter_type, const deleter_type&>::type,
    423 		   typename std::enable_if<std::is_convertible<_Up*,
    424 		   pointer>::value>::type* = 0) = delete;
    425 
    426       template<typename _Up>
    427 	unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
    428 		   typename std::enable_if<std::is_convertible<_Up*,
    429 		   pointer>::value>::type* = 0) = delete;
    430 
    431       template<typename _Up>
    432 	explicit
    433 	unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
    434 		   pointer>::value>::type* = 0) = delete;
    435     };
    436 
    437   template<typename _Tp, typename _Dp>
    438     inline void
    439     swap(unique_ptr<_Tp, _Dp>& __x,
    440 	 unique_ptr<_Tp, _Dp>& __y) noexcept
    441     { __x.swap(__y); }
    442 
    443   template<typename _Tp, typename _Dp,
    444 	   typename _Up, typename _Ep>
    445     inline bool
    446     operator==(const unique_ptr<_Tp, _Dp>& __x,
    447 	       const unique_ptr<_Up, _Ep>& __y)
    448     { return __x.get() == __y.get(); }
    449 
    450   template<typename _Tp, typename _Dp>
    451     inline bool
    452     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
    453     { return !__x; }
    454 
    455   template<typename _Tp, typename _Dp>
    456     inline bool
    457     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
    458     { return !__x; }
    459 
    460   template<typename _Tp, typename _Dp,
    461 	   typename _Up, typename _Ep>
    462     inline bool
    463     operator!=(const unique_ptr<_Tp, _Dp>& __x,
    464 	       const unique_ptr<_Up, _Ep>& __y)
    465     { return __x.get() != __y.get(); }
    466 
    467   template<typename _Tp, typename _Dp>
    468     inline bool
    469     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
    470     { return (bool)__x; }
    471 
    472   template<typename _Tp, typename _Dp>
    473     inline bool
    474     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
    475     { return (bool)__x; }
    476 
    477   template<typename _Tp, typename _Dp,
    478 	   typename _Up, typename _Ep>
    479     inline bool
    480     operator<(const unique_ptr<_Tp, _Dp>& __x,
    481 	      const unique_ptr<_Up, _Ep>& __y)
    482     {
    483       typedef typename
    484 	std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
    485 	                 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
    486       return std::less<_CT>()(__x.get(), __y.get());
    487     }
    488 
    489   template<typename _Tp, typename _Dp>
    490     inline bool
    491     operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    492     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
    493 								 nullptr); }
    494 
    495   template<typename _Tp, typename _Dp>
    496     inline bool
    497     operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    498     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
    499 								 __x.get()); }
    500 
    501   template<typename _Tp, typename _Dp,
    502 	   typename _Up, typename _Ep>
    503     inline bool
    504     operator<=(const unique_ptr<_Tp, _Dp>& __x,
    505 	       const unique_ptr<_Up, _Ep>& __y)
    506     { return !(__y < __x); }
    507 
    508   template<typename _Tp, typename _Dp>
    509     inline bool
    510     operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    511     { return !(nullptr < __x); }
    512 
    513   template<typename _Tp, typename _Dp>
    514     inline bool
    515     operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    516     { return !(__x < nullptr); }
    517 
    518   template<typename _Tp, typename _Dp,
    519 	   typename _Up, typename _Ep>
    520     inline bool
    521     operator>(const unique_ptr<_Tp, _Dp>& __x,
    522 	      const unique_ptr<_Up, _Ep>& __y)
    523     { return (__y < __x); }
    524 
    525   template<typename _Tp, typename _Dp>
    526     inline bool
    527     operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    528     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
    529 								 __x.get()); }
    530 
    531   template<typename _Tp, typename _Dp>
    532     inline bool
    533     operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    534     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
    535 								 nullptr); }
    536 
    537   template<typename _Tp, typename _Dp,
    538 	   typename _Up, typename _Ep>
    539     inline bool
    540     operator>=(const unique_ptr<_Tp, _Dp>& __x,
    541 	       const unique_ptr<_Up, _Ep>& __y)
    542     { return !(__x < __y); }
    543 
    544   template<typename _Tp, typename _Dp>
    545     inline bool
    546     operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    547     { return !(__x < nullptr); }
    548 
    549   template<typename _Tp, typename _Dp>
    550     inline bool
    551     operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
    552     { return !(nullptr < __x); }
    553 
    554   /// std::hash specialization for unique_ptr.
    555   template<typename _Tp, typename _Dp>
    556     struct hash<unique_ptr<_Tp, _Dp>>
    557     : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
    558     {
    559       size_t
    560       operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
    561       {
    562 	typedef unique_ptr<_Tp, _Dp> _UP;
    563 	return std::hash<typename _UP::pointer>()(__u.get());
    564       }
    565     };
    566 
    567   // @} group pointer_abstractions
    568 
    569 _GLIBCXX_END_NAMESPACE_VERSION
    570 } // namespace
    571 
    572 #endif /* _UNIQUE_PTR_H */
    573