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() = 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>&) { }
     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() = 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()
    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)
    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)
    128       : _M_t(__p, __d) { }
    129 
    130       unique_ptr(pointer __p,
    131 	  typename std::remove_reference<deleter_type>::type&& __d)
    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)
    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)
    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)
    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)
    165 	: _M_t(__u.release(), deleter_type()) { }
    166 #endif
    167 
    168       // Destructor.
    169       ~unique_ptr() { reset(); }
    170 
    171       // Assignment.
    172       unique_ptr&
    173       operator=(unique_ptr&& __u)
    174       {
    175 	reset(__u.release());
    176 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
    177 	return *this;
    178       }
    179 
    180       template<typename _Up, typename _Ep, typename = typename
    181 	std::enable_if
    182 	  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
    183 			       pointer>::value
    184 	   && !std::is_array<_Up>::value>::type>
    185 	unique_ptr&
    186 	operator=(unique_ptr<_Up, _Ep>&& __u)
    187 	{
    188 	  reset(__u.release());
    189 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
    190 	  return *this;
    191 	}
    192 
    193       unique_ptr&
    194       operator=(nullptr_t)
    195       {
    196 	reset();
    197 	return *this;
    198       }
    199 
    200       // Observers.
    201       typename std::add_lvalue_reference<element_type>::type
    202       operator*() const
    203       {
    204 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    205 	return *get();
    206       }
    207 
    208       pointer
    209       operator->() const
    210       {
    211 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    212 	return get();
    213       }
    214 
    215       pointer
    216       get() const
    217       { return std::get<0>(_M_t); }
    218 
    219       deleter_type&
    220       get_deleter()
    221       { return std::get<1>(_M_t); }
    222 
    223       const deleter_type&
    224       get_deleter() const
    225       { return std::get<1>(_M_t); }
    226 
    227       explicit operator bool() const
    228       { return get() == pointer() ? false : true; }
    229 
    230       // Modifiers.
    231       pointer
    232       release()
    233       {
    234 	pointer __p = get();
    235 	std::get<0>(_M_t) = pointer();
    236 	return __p;
    237       }
    238 
    239       void
    240       reset(pointer __p = pointer())
    241       {
    242 	using std::swap;
    243 	swap(std::get<0>(_M_t), __p);
    244 	if (__p != pointer())
    245 	  get_deleter()(__p);
    246       }
    247 
    248       void
    249       swap(unique_ptr& __u)
    250       {
    251 	using std::swap;
    252 	swap(_M_t, __u._M_t);
    253       }
    254 
    255       // Disable copy from lvalue.
    256       unique_ptr(const unique_ptr&) = delete;
    257       unique_ptr& operator=(const unique_ptr&) = delete;
    258   };
    259 
    260   /// 20.7.12.3 unique_ptr for array objects with a runtime length
    261   // [unique.ptr.runtime]
    262   // _GLIBCXX_RESOLVE_LIB_DEFECTS
    263   // DR 740 - omit specialization for array objects with a compile time length
    264   template<typename _Tp, typename _Dp>
    265     class unique_ptr<_Tp[], _Dp>
    266     {
    267       typedef std::tuple<_Tp*, _Dp>  	__tuple_type;
    268       __tuple_type 			_M_t;
    269 
    270     public:
    271       typedef _Tp*		 	pointer;
    272       typedef _Tp		 	element_type;
    273       typedef _Dp                       deleter_type;
    274 
    275       // Constructors.
    276       constexpr unique_ptr()
    277       : _M_t()
    278       { static_assert(!std::is_pointer<deleter_type>::value,
    279 		     "constructed with null function pointer deleter"); }
    280 
    281       explicit
    282       unique_ptr(pointer __p)
    283       : _M_t(__p, deleter_type())
    284       { static_assert(!std::is_pointer<deleter_type>::value,
    285 		     "constructed with null function pointer deleter"); }
    286 
    287       unique_ptr(pointer __p,
    288 	  typename std::conditional<std::is_reference<deleter_type>::value,
    289 	      deleter_type, const deleter_type&>::type __d)
    290       : _M_t(__p, __d) { }
    291 
    292       unique_ptr(pointer __p,
    293 		 typename std::remove_reference<deleter_type>::type && __d)
    294       : _M_t(std::move(__p), std::move(__d))
    295       { static_assert(!std::is_reference<deleter_type>::value,
    296 		      "rvalue deleter bound to reference"); }
    297 
    298       constexpr unique_ptr(nullptr_t)
    299       : _M_t()
    300       { static_assert(!std::is_pointer<deleter_type>::value,
    301 		     "constructed with null function pointer deleter"); }
    302 
    303       // Move constructors.
    304       unique_ptr(unique_ptr&& __u)
    305       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
    306 
    307       template<typename _Up, typename _Ep>
    308 	unique_ptr(unique_ptr<_Up, _Ep>&& __u)
    309 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
    310 	{ }
    311 
    312       // Destructor.
    313       ~unique_ptr() { reset(); }
    314 
    315       // Assignment.
    316       unique_ptr&
    317       operator=(unique_ptr&& __u)
    318       {
    319 	reset(__u.release());
    320 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
    321 	return *this;
    322       }
    323 
    324       template<typename _Up, typename _Ep>
    325 	unique_ptr&
    326 	operator=(unique_ptr<_Up, _Ep>&& __u)
    327 	{
    328 	  reset(__u.release());
    329 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
    330 	  return *this;
    331 	}
    332 
    333       unique_ptr&
    334       operator=(nullptr_t)
    335       {
    336 	reset();
    337 	return *this;
    338       }
    339 
    340       // Observers.
    341       typename std::add_lvalue_reference<element_type>::type
    342       operator[](size_t __i) const
    343       {
    344 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
    345 	return get()[__i];
    346       }
    347 
    348       pointer
    349       get() const
    350       { return std::get<0>(_M_t); }
    351 
    352       deleter_type&
    353       get_deleter()
    354       { return std::get<1>(_M_t); }
    355 
    356       const deleter_type&
    357       get_deleter() const
    358       { return std::get<1>(_M_t); }
    359 
    360       explicit operator bool() const
    361       { return get() == pointer() ? false : true; }
    362 
    363       // Modifiers.
    364       pointer
    365       release()
    366       {
    367 	pointer __p = get();
    368 	std::get<0>(_M_t) = pointer();
    369 	return __p;
    370       }
    371 
    372       void
    373       reset(pointer __p = pointer())
    374       {
    375 	using std::swap;
    376 	swap(std::get<0>(_M_t), __p);
    377 	if (__p != nullptr)
    378 	  get_deleter()(__p);
    379       }
    380 
    381       void
    382       reset(nullptr_t)
    383       {
    384 	pointer __p = get();
    385 	std::get<0>(_M_t) = pointer();
    386 	if (__p != nullptr)
    387 	  get_deleter()(__p);
    388       }
    389 
    390       // DR 821.
    391       template<typename _Up>
    392 	void reset(_Up) = delete;
    393 
    394       void
    395       swap(unique_ptr& __u)
    396       {
    397 	using std::swap;
    398 	swap(_M_t, __u._M_t);
    399       }
    400 
    401       // Disable copy from lvalue.
    402       unique_ptr(const unique_ptr&) = delete;
    403       unique_ptr& operator=(const unique_ptr&) = delete;
    404 
    405       // Disable construction from convertible pointer types.
    406       // (N2315 - 20.6.5.3.1)
    407       template<typename _Up>
    408 	unique_ptr(_Up*, typename
    409 		   std::conditional<std::is_reference<deleter_type>::value,
    410 		   deleter_type, const deleter_type&>::type,
    411 		   typename std::enable_if<std::is_convertible<_Up*,
    412 		   pointer>::value>::type* = 0) = delete;
    413 
    414       template<typename _Up>
    415 	unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
    416 		   typename std::enable_if<std::is_convertible<_Up*,
    417 		   pointer>::value>::type* = 0) = delete;
    418 
    419       template<typename _Up>
    420 	explicit
    421 	unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
    422 		   pointer>::value>::type* = 0) = delete;
    423   };
    424 
    425   template<typename _Tp, typename _Dp>
    426     inline void
    427     swap(unique_ptr<_Tp, _Dp>& __x,
    428 	 unique_ptr<_Tp, _Dp>& __y)
    429     { __x.swap(__y); }
    430 
    431   template<typename _Tp, typename _Dp,
    432 	   typename _Up, typename _Ep>
    433     inline bool
    434     operator==(const unique_ptr<_Tp, _Dp>& __x,
    435 	       const unique_ptr<_Up, _Ep>& __y)
    436     { return __x.get() == __y.get(); }
    437 
    438   template<typename _Tp, typename _Dp>
    439     inline bool
    440     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    441     { return __x.get() == nullptr; }
    442 
    443   template<typename _Tp, typename _Dp>
    444     inline bool
    445     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
    446     { return nullptr == __y.get(); }
    447 
    448   template<typename _Tp, typename _Dp,
    449 	   typename _Up, typename _Ep>
    450     inline bool
    451     operator!=(const unique_ptr<_Tp, _Dp>& __x,
    452 	       const unique_ptr<_Up, _Ep>& __y)
    453     { return !(__x.get() == __y.get()); }
    454 
    455   template<typename _Tp, typename _Dp>
    456     inline bool
    457     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
    458     { return __x.get() != nullptr; }
    459 
    460   template<typename _Tp, typename _Dp>
    461     inline bool
    462     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
    463     { return nullptr != __y.get(); }
    464 
    465   template<typename _Tp, typename _Dp,
    466 	   typename _Up, typename _Ep>
    467     inline bool
    468     operator<(const unique_ptr<_Tp, _Dp>& __x,
    469 	      const unique_ptr<_Up, _Ep>& __y)
    470     { return __x.get() < __y.get(); }
    471 
    472   template<typename _Tp, typename _Dp,
    473 	   typename _Up, typename _Ep>
    474     inline bool
    475     operator<=(const unique_ptr<_Tp, _Dp>& __x,
    476 	       const unique_ptr<_Up, _Ep>& __y)
    477     { return !(__y.get() < __x.get()); }
    478 
    479   template<typename _Tp, typename _Dp,
    480 	   typename _Up, typename _Ep>
    481     inline bool
    482     operator>(const unique_ptr<_Tp, _Dp>& __x,
    483 	      const unique_ptr<_Up, _Ep>& __y)
    484     { return __y.get() < __x.get(); }
    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   /// std::hash specialization for unique_ptr.
    494   template<typename _Tp, typename _Dp>
    495     struct hash<unique_ptr<_Tp, _Dp>>
    496     : public std::unary_function<unique_ptr<_Tp, _Dp>, size_t>
    497     {
    498       size_t
    499       operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
    500       {
    501 	typedef unique_ptr<_Tp, _Dp> _UP;
    502 	return std::hash<typename _UP::pointer>()(__u.get());
    503       }
    504     };
    505 
    506   // @} group pointer_abstractions
    507 
    508 _GLIBCXX_END_NAMESPACE_VERSION
    509 } // namespace
    510 
    511 #endif /* _UNIQUE_PTR_H */
    512