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