1 // unique_ptr implementation -*- C++ -*- 2 3 // Copyright (C) 2008, 2009, 2010 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 unique_ptr.h 26 * This is an internal header file, included by other library headers. 27 * You should not attempt to use it directly. 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 _GLIBCXX_BEGIN_NAMESPACE(std) 40 41 /** 42 * @addtogroup pointer_abstractions 43 * @{ 44 */ 45 46 /// Primary template, default_delete. 47 template<typename _Tp> 48 struct default_delete 49 { 50 default_delete() { } 51 52 template<typename _Up> 53 default_delete(const default_delete<_Up>&) { } 54 55 void 56 operator()(_Tp* __ptr) const 57 { 58 static_assert(sizeof(_Tp)>0, 59 "can't delete pointer to incomplete type"); 60 delete __ptr; 61 } 62 }; 63 64 // _GLIBCXX_RESOLVE_LIB_DEFECTS 65 // DR 740 - omit specialization for array objects with a compile time length 66 /// Specialization, default_delete. 67 template<typename _Tp> 68 struct default_delete<_Tp[]> 69 { 70 void 71 operator()(_Tp* __ptr) const 72 { 73 static_assert(sizeof(_Tp)>0, 74 "can't delete pointer to incomplete type"); 75 delete [] __ptr; 76 } 77 }; 78 79 /// 20.7.12.2 unique_ptr for single objects. 80 template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> > 81 class unique_ptr 82 { 83 typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; 84 typedef _Tp* unique_ptr::* __unspecified_pointer_type; 85 86 public: 87 typedef _Tp* pointer; 88 typedef _Tp element_type; 89 typedef _Tp_Deleter deleter_type; 90 91 // Constructors. 92 unique_ptr() 93 : _M_t(pointer(), deleter_type()) 94 { static_assert(!std::is_pointer<deleter_type>::value, 95 "constructed with null function pointer deleter"); } 96 97 explicit 98 unique_ptr(pointer __p) 99 : _M_t(__p, deleter_type()) 100 { static_assert(!std::is_pointer<deleter_type>::value, 101 "constructed with null function pointer deleter"); } 102 103 unique_ptr(pointer __p, 104 typename std::conditional<std::is_reference<deleter_type>::value, 105 deleter_type, const deleter_type&>::type __d) 106 : _M_t(__p, __d) { } 107 108 unique_ptr(pointer __p, 109 typename std::remove_reference<deleter_type>::type&& __d) 110 : _M_t(std::move(__p), std::move(__d)) 111 { static_assert(!std::is_reference<deleter_type>::value, 112 "rvalue deleter bound to reference"); } 113 114 // Move constructors. 115 unique_ptr(unique_ptr&& __u) 116 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } 117 118 template<typename _Up, typename _Up_Deleter> 119 unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 120 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) 121 { } 122 123 // Destructor. 124 ~unique_ptr() { reset(); } 125 126 // Assignment. 127 unique_ptr& 128 operator=(unique_ptr&& __u) 129 { 130 reset(__u.release()); 131 get_deleter() = std::move(__u.get_deleter()); 132 return *this; 133 } 134 135 template<typename _Up, typename _Up_Deleter> 136 unique_ptr& 137 operator=(unique_ptr<_Up, _Up_Deleter>&& __u) 138 { 139 reset(__u.release()); 140 get_deleter() = std::move(__u.get_deleter()); 141 return *this; 142 } 143 144 unique_ptr& 145 operator=(__unspecified_pointer_type) 146 { 147 reset(); 148 return *this; 149 } 150 151 // Observers. 152 typename std::add_lvalue_reference<element_type>::type 153 operator*() const 154 { 155 _GLIBCXX_DEBUG_ASSERT(get() != pointer()); 156 return *get(); 157 } 158 159 pointer 160 operator->() const 161 { 162 _GLIBCXX_DEBUG_ASSERT(get() != pointer()); 163 return get(); 164 } 165 166 pointer 167 get() const 168 { return std::get<0>(_M_t); } 169 170 deleter_type& 171 get_deleter() 172 { return std::get<1>(_M_t); } 173 174 const deleter_type& 175 get_deleter() const 176 { return std::get<1>(_M_t); } 177 178 explicit operator bool() const 179 { return get() == pointer() ? false : true; } 180 181 // Modifiers. 182 pointer 183 release() 184 { 185 pointer __p = get(); 186 std::get<0>(_M_t) = pointer(); 187 return __p; 188 } 189 190 void 191 reset(pointer __p = pointer()) 192 { 193 using std::swap; 194 swap(std::get<0>(_M_t), __p); 195 if (__p != pointer()) 196 get_deleter()(__p); 197 } 198 199 void 200 swap(unique_ptr& __u) 201 { 202 using std::swap; 203 swap(_M_t, __u._M_t); 204 } 205 206 // Disable copy from lvalue. 207 unique_ptr(const unique_ptr&) = delete; 208 unique_ptr& operator=(const unique_ptr&) = delete; 209 210 private: 211 __tuple_type _M_t; 212 }; 213 214 /// 20.7.12.3 unique_ptr for array objects with a runtime length 215 // [unique.ptr.runtime] 216 // _GLIBCXX_RESOLVE_LIB_DEFECTS 217 // DR 740 - omit specialization for array objects with a compile time length 218 template<typename _Tp, typename _Tp_Deleter> 219 class unique_ptr<_Tp[], _Tp_Deleter> 220 { 221 typedef std::tuple<_Tp*, _Tp_Deleter> __tuple_type; 222 typedef _Tp* unique_ptr::* __unspecified_pointer_type; 223 224 public: 225 typedef _Tp* pointer; 226 typedef _Tp element_type; 227 typedef _Tp_Deleter deleter_type; 228 229 // Constructors. 230 unique_ptr() 231 : _M_t(pointer(), deleter_type()) 232 { static_assert(!std::is_pointer<deleter_type>::value, 233 "constructed with null function pointer deleter"); } 234 235 explicit 236 unique_ptr(pointer __p) 237 : _M_t(__p, deleter_type()) 238 { static_assert(!std::is_pointer<deleter_type>::value, 239 "constructed with null function pointer deleter"); } 240 241 unique_ptr(pointer __p, 242 typename std::conditional<std::is_reference<deleter_type>::value, 243 deleter_type, const deleter_type&>::type __d) 244 : _M_t(__p, __d) { } 245 246 unique_ptr(pointer __p, 247 typename std::remove_reference<deleter_type>::type && __d) 248 : _M_t(std::move(__p), std::move(__d)) 249 { static_assert(!std::is_reference<deleter_type>::value, 250 "rvalue deleter bound to reference"); } 251 252 // Move constructors. 253 unique_ptr(unique_ptr&& __u) 254 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } 255 256 template<typename _Up, typename _Up_Deleter> 257 unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 258 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) 259 { } 260 261 // Destructor. 262 ~unique_ptr() { reset(); } 263 264 // Assignment. 265 unique_ptr& 266 operator=(unique_ptr&& __u) 267 { 268 reset(__u.release()); 269 get_deleter() = std::move(__u.get_deleter()); 270 return *this; 271 } 272 273 template<typename _Up, typename _Up_Deleter> 274 unique_ptr& 275 operator=(unique_ptr<_Up, _Up_Deleter>&& __u) 276 { 277 reset(__u.release()); 278 get_deleter() = std::move(__u.get_deleter()); 279 return *this; 280 } 281 282 unique_ptr& 283 operator=(__unspecified_pointer_type) 284 { 285 reset(); 286 return *this; 287 } 288 289 // Observers. 290 typename std::add_lvalue_reference<element_type>::type 291 operator[](size_t __i) const 292 { 293 _GLIBCXX_DEBUG_ASSERT(get() != pointer()); 294 return get()[__i]; 295 } 296 297 pointer 298 get() const 299 { return std::get<0>(_M_t); } 300 301 deleter_type& 302 get_deleter() 303 { return std::get<1>(_M_t); } 304 305 const deleter_type& 306 get_deleter() const 307 { return std::get<1>(_M_t); } 308 309 explicit operator bool() const 310 { return get() == pointer() ? false : true; } 311 312 // Modifiers. 313 pointer 314 release() 315 { 316 pointer __p = get(); 317 std::get<0>(_M_t) = pointer(); 318 return __p; 319 } 320 321 void 322 reset(pointer __p = pointer()) 323 { 324 using std::swap; 325 swap(std::get<0>(_M_t), __p); 326 if (__p != pointer()) 327 get_deleter()(__p); 328 } 329 330 // DR 821. 331 template<typename _Up> 332 void reset(_Up) = delete; 333 334 void 335 swap(unique_ptr& __u) 336 { 337 using std::swap; 338 swap(_M_t, __u._M_t); 339 } 340 341 // Disable copy from lvalue. 342 unique_ptr(const unique_ptr&) = delete; 343 unique_ptr& operator=(const unique_ptr&) = delete; 344 345 // Disable construction from convertible pointer types. 346 // (N2315 - 20.6.5.3.1) 347 template<typename _Up> 348 unique_ptr(_Up*, typename 349 std::conditional<std::is_reference<deleter_type>::value, 350 deleter_type, const deleter_type&>::type, 351 typename std::enable_if<std::is_convertible<_Up*, 352 pointer>::value>::type* = 0) = delete; 353 354 template<typename _Up> 355 unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&, 356 typename std::enable_if<std::is_convertible<_Up*, 357 pointer>::value>::type* = 0) = delete; 358 359 template<typename _Up> 360 explicit 361 unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 362 pointer>::value>::type* = 0) = delete; 363 364 private: 365 __tuple_type _M_t; 366 }; 367 368 template<typename _Tp, typename _Tp_Deleter> 369 inline void 370 swap(unique_ptr<_Tp, _Tp_Deleter>& __x, 371 unique_ptr<_Tp, _Tp_Deleter>& __y) 372 { __x.swap(__y); } 373 374 template<typename _Tp, typename _Tp_Deleter, 375 typename _Up, typename _Up_Deleter> 376 inline bool 377 operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x, 378 const unique_ptr<_Up, _Up_Deleter>& __y) 379 { return __x.get() == __y.get(); } 380 381 template<typename _Tp, typename _Tp_Deleter, 382 typename _Up, typename _Up_Deleter> 383 inline bool 384 operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x, 385 const unique_ptr<_Up, _Up_Deleter>& __y) 386 { return !(__x.get() == __y.get()); } 387 388 template<typename _Tp, typename _Tp_Deleter, 389 typename _Up, typename _Up_Deleter> 390 inline bool 391 operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x, 392 const unique_ptr<_Up, _Up_Deleter>& __y) 393 { return __x.get() < __y.get(); } 394 395 template<typename _Tp, typename _Tp_Deleter, 396 typename _Up, typename _Up_Deleter> 397 inline bool 398 operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x, 399 const unique_ptr<_Up, _Up_Deleter>& __y) 400 { return !(__y.get() < __x.get()); } 401 402 template<typename _Tp, typename _Tp_Deleter, 403 typename _Up, typename _Up_Deleter> 404 inline bool 405 operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x, 406 const unique_ptr<_Up, _Up_Deleter>& __y) 407 { return __y.get() < __x.get(); } 408 409 template<typename _Tp, typename _Tp_Deleter, 410 typename _Up, typename _Up_Deleter> 411 inline bool 412 operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x, 413 const unique_ptr<_Up, _Up_Deleter>& __y) 414 { return !(__x.get() < __y.get()); } 415 416 // @} group pointer_abstractions 417 418 _GLIBCXX_END_NAMESPACE 419 420 #endif /* _UNIQUE_PTR_H */ 421