libstdc++
|
00001 // unique_ptr implementation -*- C++ -*- 00002 00003 // Copyright (C) 2008, 2009 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 unique_ptr.h 00026 * This is an internal header file, included by other library headers. 00027 * You should not attempt to use it directly. 00028 */ 00029 00030 #ifndef _UNIQUE_PTR_H 00031 #define _UNIQUE_PTR_H 1 00032 00033 #ifndef __GXX_EXPERIMENTAL_CXX0X__ 00034 # include <c++0x_warning.h> 00035 #endif 00036 00037 #include <bits/c++config.h> 00038 #include <debug/debug.h> 00039 #include <type_traits> 00040 #include <utility> 00041 #include <tuple> 00042 00043 _GLIBCXX_BEGIN_NAMESPACE(std) 00044 00045 /** 00046 * @addtogroup pointer_abstractions 00047 * @{ 00048 */ 00049 00050 /// Primary template, default_delete. 00051 template<typename _Tp> 00052 struct default_delete 00053 { 00054 default_delete() { } 00055 00056 template<typename _Up> 00057 default_delete(const default_delete<_Up>&) { } 00058 00059 void 00060 operator()(_Tp* __ptr) const 00061 { 00062 static_assert(sizeof(_Tp)>0, 00063 "can't delete pointer to incomplete type"); 00064 delete __ptr; 00065 } 00066 }; 00067 00068 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00069 // DR 740 - omit specialization for array objects with a compile time length 00070 /// Specialization, default_delete. 00071 template<typename _Tp> 00072 struct default_delete<_Tp[]> 00073 { 00074 void 00075 operator()(_Tp* __ptr) const 00076 { 00077 static_assert(sizeof(_Tp)>0, 00078 "can't delete pointer to incomplete type"); 00079 delete [] __ptr; 00080 } 00081 }; 00082 00083 /// 20.7.12.2 unique_ptr for single objects. 00084 template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> > 00085 class unique_ptr 00086 { 00087 typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; 00088 typedef __tuple_type unique_ptr::* __unspecified_bool_type; 00089 typedef _Tp* unique_ptr::* __unspecified_pointer_type; 00090 00091 public: 00092 typedef _Tp* pointer; 00093 typedef _Tp element_type; 00094 typedef _Tp_Deleter deleter_type; 00095 00096 // Constructors. 00097 unique_ptr() 00098 : _M_t(pointer(), deleter_type()) 00099 { static_assert(!std::is_pointer<deleter_type>::value, 00100 "constructed with null function pointer deleter"); } 00101 00102 explicit 00103 unique_ptr(pointer __p) 00104 : _M_t(__p, deleter_type()) 00105 { static_assert(!std::is_pointer<deleter_type>::value, 00106 "constructed with null function pointer deleter"); } 00107 00108 unique_ptr(pointer __p, 00109 typename std::conditional<std::is_reference<deleter_type>::value, 00110 deleter_type, const deleter_type&>::type __d) 00111 : _M_t(__p, __d) { } 00112 00113 unique_ptr(pointer __p, 00114 typename std::remove_reference<deleter_type>::type&& __d) 00115 : _M_t(std::move(__p), std::move(__d)) 00116 { static_assert(!std::is_reference<deleter_type>::value, 00117 "rvalue deleter bound to reference"); } 00118 00119 // Move constructors. 00120 unique_ptr(unique_ptr&& __u) 00121 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } 00122 00123 template<typename _Up, typename _Up_Deleter> 00124 unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 00125 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) 00126 { } 00127 00128 // Destructor. 00129 ~unique_ptr() { reset(); } 00130 00131 // Assignment. 00132 unique_ptr& 00133 operator=(unique_ptr&& __u) 00134 { 00135 reset(__u.release()); 00136 get_deleter() = std::move(__u.get_deleter()); 00137 return *this; 00138 } 00139 00140 template<typename _Up, typename _Up_Deleter> 00141 unique_ptr& 00142 operator=(unique_ptr<_Up, _Up_Deleter>&& __u) 00143 { 00144 reset(__u.release()); 00145 get_deleter() = std::move(__u.get_deleter()); 00146 return *this; 00147 } 00148 00149 unique_ptr& 00150 operator=(__unspecified_pointer_type) 00151 { 00152 reset(); 00153 return *this; 00154 } 00155 00156 // Observers. 00157 typename std::add_lvalue_reference<element_type>::type operator*() const 00158 { 00159 _GLIBCXX_DEBUG_ASSERT(get() != 0); 00160 return *get(); 00161 } 00162 00163 pointer 00164 operator->() const 00165 { 00166 _GLIBCXX_DEBUG_ASSERT(get() != 0); 00167 return get(); 00168 } 00169 00170 pointer 00171 get() const 00172 { return std::get<0>(_M_t); } 00173 00174 typename std::add_lvalue_reference<deleter_type>::type 00175 get_deleter() 00176 { return std::get<1>(_M_t); } 00177 00178 typename std::add_lvalue_reference< 00179 typename std::add_const<deleter_type>::type 00180 >::type 00181 get_deleter() const 00182 { return std::get<1>(_M_t); } 00183 00184 operator __unspecified_bool_type () const 00185 { return get() == 0 ? 0 : &unique_ptr::_M_t; } 00186 00187 // Modifiers. 00188 pointer 00189 release() 00190 { 00191 pointer __p = get(); 00192 std::get<0>(_M_t) = 0; 00193 return __p; 00194 } 00195 00196 void 00197 reset(pointer __p = pointer()) 00198 { 00199 if (__p != get()) 00200 { 00201 get_deleter()(get()); 00202 std::get<0>(_M_t) = __p; 00203 } 00204 } 00205 00206 void 00207 swap(unique_ptr&& __u) 00208 { 00209 using std::swap; 00210 swap(_M_t, __u._M_t); 00211 } 00212 00213 // Disable copy from lvalue. 00214 unique_ptr(const unique_ptr&) = delete; 00215 00216 template<typename _Up, typename _Up_Deleter> 00217 unique_ptr(const unique_ptr<_Up, _Up_Deleter>&) = delete; 00218 00219 unique_ptr& operator=(const unique_ptr&) = delete; 00220 00221 template<typename _Up, typename _Up_Deleter> 00222 unique_ptr& operator=(const unique_ptr<_Up, _Up_Deleter>&) = delete; 00223 00224 private: 00225 __tuple_type _M_t; 00226 }; 00227 00228 /// 20.7.12.3 unique_ptr for array objects with a runtime length 00229 // [unique.ptr.runtime] 00230 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00231 // DR 740 - omit specialization for array objects with a compile time length 00232 template<typename _Tp, typename _Tp_Deleter> 00233 class unique_ptr<_Tp[], _Tp_Deleter> 00234 { 00235 typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; 00236 typedef __tuple_type unique_ptr::* __unspecified_bool_type; 00237 typedef _Tp* unique_ptr::* __unspecified_pointer_type; 00238 00239 public: 00240 typedef _Tp* pointer; 00241 typedef _Tp element_type; 00242 typedef _Tp_Deleter deleter_type; 00243 00244 // Constructors. 00245 unique_ptr() 00246 : _M_t(pointer(), deleter_type()) 00247 { static_assert(!std::is_pointer<deleter_type>::value, 00248 "constructed with null function pointer deleter"); } 00249 00250 explicit 00251 unique_ptr(pointer __p) 00252 : _M_t(__p, deleter_type()) 00253 { static_assert(!std::is_pointer<deleter_type>::value, 00254 "constructed with null function pointer deleter"); } 00255 00256 unique_ptr(pointer __p, 00257 typename std::conditional<std::is_reference<deleter_type>::value, 00258 deleter_type, const deleter_type&>::type __d) 00259 : _M_t(__p, __d) { } 00260 00261 unique_ptr(pointer __p, 00262 typename std::remove_reference<deleter_type>::type && __d) 00263 : _M_t(std::move(__p), std::move(__d)) 00264 { static_assert(!std::is_reference<deleter_type>::value, 00265 "rvalue deleter bound to reference"); } 00266 00267 // Move constructors. 00268 unique_ptr(unique_ptr&& __u) 00269 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } 00270 00271 template<typename _Up, typename _Up_Deleter> 00272 unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 00273 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) 00274 { } 00275 00276 // Destructor. 00277 ~unique_ptr() { reset(); } 00278 00279 // Assignment. 00280 unique_ptr& 00281 operator=(unique_ptr&& __u) 00282 { 00283 reset(__u.release()); 00284 get_deleter() = std::move(__u.get_deleter()); 00285 return *this; 00286 } 00287 00288 template<typename _Up, typename _Up_Deleter> 00289 unique_ptr& 00290 operator=(unique_ptr<_Up, _Up_Deleter>&& __u) 00291 { 00292 reset(__u.release()); 00293 get_deleter() = std::move(__u.get_deleter()); 00294 return *this; 00295 } 00296 00297 unique_ptr& 00298 operator=(__unspecified_pointer_type) 00299 { 00300 reset(); 00301 return *this; 00302 } 00303 00304 // Observers. 00305 typename std::add_lvalue_reference<element_type>::type 00306 operator[](size_t __i) const 00307 { 00308 _GLIBCXX_DEBUG_ASSERT(get() != 0); 00309 return get()[__i]; 00310 } 00311 00312 pointer 00313 get() const 00314 { return std::get<0>(_M_t); } 00315 00316 typename std::add_lvalue_reference<deleter_type>::type 00317 get_deleter() 00318 { return std::get<1>(_M_t); } 00319 00320 typename std::add_lvalue_reference< 00321 typename std::add_const<deleter_type>::type 00322 >::type 00323 get_deleter() const 00324 { return std::get<1>(_M_t); } 00325 00326 operator __unspecified_bool_type () const 00327 { return get() == 0 ? 0 : &unique_ptr::_M_t; } 00328 00329 // Modifiers. 00330 pointer 00331 release() 00332 { 00333 pointer __p = get(); 00334 std::get<0>(_M_t) = 0; 00335 return __p; 00336 } 00337 00338 void 00339 reset(pointer __p = pointer()) 00340 { 00341 if (__p != get()) 00342 { 00343 get_deleter()(get()); 00344 std::get<0>(_M_t) = __p; 00345 } 00346 } 00347 00348 // DR 821. 00349 template<typename _Up> 00350 void reset(_Up) = delete; 00351 00352 void 00353 swap(unique_ptr&& __u) 00354 { 00355 using std::swap; 00356 swap(_M_t, __u._M_t); 00357 } 00358 00359 // Disable copy from lvalue. 00360 unique_ptr(const unique_ptr&) = delete; 00361 unique_ptr& operator=(const unique_ptr&) = delete; 00362 00363 // Disable construction from convertible pointer types. 00364 // (N2315 - 20.6.5.3.1) 00365 template<typename _Up> 00366 unique_ptr(_Up*, typename 00367 std::conditional<std::is_reference<deleter_type>::value, 00368 deleter_type, const deleter_type&>::type, 00369 typename std::enable_if<std::is_convertible<_Up*, 00370 pointer>::value>::type* = 0) = delete; 00371 00372 template<typename _Up> 00373 unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&, 00374 typename std::enable_if<std::is_convertible<_Up*, 00375 pointer>::value>::type* = 0) = delete; 00376 00377 template<typename _Up> 00378 explicit 00379 unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 00380 pointer>::value>::type* = 0) = delete; 00381 00382 private: 00383 __tuple_type _M_t; 00384 }; 00385 00386 template<typename _Tp, typename _Tp_Deleter> 00387 inline void 00388 swap(unique_ptr<_Tp, _Tp_Deleter>& __x, 00389 unique_ptr<_Tp, _Tp_Deleter>& __y) 00390 { __x.swap(__y); } 00391 00392 template<typename _Tp, typename _Tp_Deleter> 00393 inline void 00394 swap(unique_ptr<_Tp, _Tp_Deleter>&& __x, 00395 unique_ptr<_Tp, _Tp_Deleter>& __y) 00396 { __x.swap(__y); } 00397 00398 template<typename _Tp, typename _Tp_Deleter> 00399 inline void 00400 swap(unique_ptr<_Tp, _Tp_Deleter>& __x, 00401 unique_ptr<_Tp, _Tp_Deleter>&& __y) 00402 { __x.swap(__y); } 00403 00404 template<typename _Tp, typename _Tp_Deleter, 00405 typename _Up, typename _Up_Deleter> 00406 inline bool 00407 operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x, 00408 const unique_ptr<_Up, _Up_Deleter>& __y) 00409 { return __x.get() == __y.get(); } 00410 00411 template<typename _Tp, typename _Tp_Deleter, 00412 typename _Up, typename _Up_Deleter> 00413 inline bool 00414 operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x, 00415 const unique_ptr<_Up, _Up_Deleter>& __y) 00416 { return !(__x.get() == __y.get()); } 00417 00418 template<typename _Tp, typename _Tp_Deleter, 00419 typename _Up, typename _Up_Deleter> 00420 inline bool 00421 operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x, 00422 const unique_ptr<_Up, _Up_Deleter>& __y) 00423 { return __x.get() < __y.get(); } 00424 00425 template<typename _Tp, typename _Tp_Deleter, 00426 typename _Up, typename _Up_Deleter> 00427 inline bool 00428 operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x, 00429 const unique_ptr<_Up, _Up_Deleter>& __y) 00430 { return !(__y.get() < __x.get()); } 00431 00432 template<typename _Tp, typename _Tp_Deleter, 00433 typename _Up, typename _Up_Deleter> 00434 inline bool 00435 operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x, 00436 const unique_ptr<_Up, _Up_Deleter>& __y) 00437 { return __y.get() < __x.get(); } 00438 00439 template<typename _Tp, typename _Tp_Deleter, 00440 typename _Up, typename _Up_Deleter> 00441 inline bool 00442 operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x, 00443 const unique_ptr<_Up, _Up_Deleter>& __y) 00444 { return !(__x.get() < __y.get()); } 00445 00446 // @} group pointer_abstractions 00447 00448 _GLIBCXX_END_NAMESPACE 00449 00450 #endif /* _UNIQUE_PTR_H */