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