libstdc++
|
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 */