00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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 _GLIBCXX_BEGIN_NAMESPACE(std)
00040
00041
00042
00043
00044
00045
00046
00047 template<typename _Tp>
00048 struct default_delete
00049 {
00050 default_delete() { }
00051
00052 template<typename _Up, typename = typename
00053 std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type>
00054 default_delete(const default_delete<_Up>&) { }
00055
00056 void
00057 operator()(_Tp* __ptr) const
00058 {
00059 static_assert(sizeof(_Tp)>0,
00060 "can't delete pointer to incomplete type");
00061 delete __ptr;
00062 }
00063 };
00064
00065
00066
00067
00068 template<typename _Tp>
00069 struct default_delete<_Tp[]>
00070 {
00071 void
00072 operator()(_Tp* __ptr) const
00073 {
00074 static_assert(sizeof(_Tp)>0,
00075 "can't delete pointer to incomplete type");
00076 delete [] __ptr;
00077 }
00078 };
00079
00080
00081 template <typename _Tp, typename _Dp = default_delete<_Tp> >
00082 class unique_ptr
00083 {
00084 typedef std::tuple<_Tp*, _Dp> __tuple_type;
00085
00086
00087 class _Pointer
00088 {
00089 template<typename _Up>
00090 static typename _Up::pointer __test(typename _Up::pointer*);
00091
00092 template<typename _Up>
00093 static _Tp* __test(...);
00094
00095 typedef typename remove_reference<_Dp>::type _Del;
00096
00097 public:
00098 typedef decltype( __test<_Del>(0) ) type;
00099 };
00100
00101 public:
00102 typedef typename _Pointer::type pointer;
00103 typedef _Tp element_type;
00104 typedef _Dp deleter_type;
00105
00106
00107 unique_ptr()
00108 : _M_t(pointer(), deleter_type())
00109 { static_assert(!std::is_pointer<deleter_type>::value,
00110 "constructed with null function pointer deleter"); }
00111
00112 explicit
00113 unique_ptr(pointer __p)
00114 : _M_t(__p, deleter_type())
00115 { static_assert(!std::is_pointer<deleter_type>::value,
00116 "constructed with null function pointer deleter"); }
00117
00118 unique_ptr(pointer __p,
00119 typename std::conditional<std::is_reference<deleter_type>::value,
00120 deleter_type, const deleter_type&>::type __d)
00121 : _M_t(__p, __d) { }
00122
00123 unique_ptr(pointer __p,
00124 typename std::remove_reference<deleter_type>::type&& __d)
00125 : _M_t(std::move(__p), std::move(__d))
00126 { static_assert(!std::is_reference<deleter_type>::value,
00127 "rvalue deleter bound to reference"); }
00128
00129 unique_ptr(nullptr_t)
00130 : _M_t(pointer(), deleter_type())
00131 { }
00132
00133
00134 unique_ptr(unique_ptr&& __u)
00135 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00136
00137 template<typename _Up, typename _Ep, typename = typename
00138 std::enable_if
00139 <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
00140 pointer>::value
00141 && !std::is_array<_Up>::value
00142 && ((std::is_reference<_Dp>::value
00143 && std::is_same<_Ep, _Dp>::value)
00144 || (!std::is_reference<_Dp>::value
00145 && std::is_convertible<_Ep, _Dp>::value))>
00146 ::type>
00147 unique_ptr(unique_ptr<_Up, _Ep>&& __u)
00148 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00149 { }
00150
00151 #if _GLIBCXX_DEPRECATED
00152 template<typename _Up, typename = typename
00153 std::enable_if<std::is_convertible<_Up*, _Tp*>::value
00154 && std::is_same<_Dp,
00155 default_delete<_Tp>>::value>::type>
00156 unique_ptr(auto_ptr<_Up>&& __u)
00157 : _M_t(__u.release(), deleter_type()) { }
00158 #endif
00159
00160
00161 ~unique_ptr() { reset(); }
00162
00163
00164 unique_ptr&
00165 operator=(unique_ptr&& __u)
00166 {
00167 reset(__u.release());
00168 get_deleter() = std::move(__u.get_deleter());
00169 return *this;
00170 }
00171
00172 template<typename _Up, typename _Ep, typename = typename
00173 std::enable_if
00174 <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
00175 pointer>::value
00176 && !std::is_array<_Up>::value>::type>
00177 unique_ptr&
00178 operator=(unique_ptr<_Up, _Ep>&& __u)
00179 {
00180 reset(__u.release());
00181 get_deleter() = std::move(__u.get_deleter());
00182 return *this;
00183 }
00184
00185 unique_ptr&
00186 operator=(nullptr_t)
00187 {
00188 reset();
00189 return *this;
00190 }
00191
00192
00193 typename std::add_lvalue_reference<element_type>::type
00194 operator*() const
00195 {
00196 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00197 return *get();
00198 }
00199
00200 pointer
00201 operator->() const
00202 {
00203 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00204 return get();
00205 }
00206
00207 pointer
00208 get() const
00209 { return std::get<0>(_M_t); }
00210
00211 deleter_type&
00212 get_deleter()
00213 { return std::get<1>(_M_t); }
00214
00215 const deleter_type&
00216 get_deleter() const
00217 { return std::get<1>(_M_t); }
00218
00219 explicit operator bool() const
00220 { return get() == pointer() ? false : true; }
00221
00222
00223 pointer
00224 release()
00225 {
00226 pointer __p = get();
00227 std::get<0>(_M_t) = pointer();
00228 return __p;
00229 }
00230
00231 void
00232 reset(pointer __p = pointer())
00233 {
00234 using std::swap;
00235 swap(std::get<0>(_M_t), __p);
00236 if (__p != pointer())
00237 get_deleter()(__p);
00238 }
00239
00240 void
00241 swap(unique_ptr& __u)
00242 {
00243 using std::swap;
00244 swap(_M_t, __u._M_t);
00245 }
00246
00247
00248 unique_ptr(const unique_ptr&) = delete;
00249 unique_ptr& operator=(const unique_ptr&) = delete;
00250
00251 private:
00252 __tuple_type _M_t;
00253 };
00254
00255
00256
00257
00258
00259 template<typename _Tp, typename _Dp>
00260 class unique_ptr<_Tp[], _Dp>
00261 {
00262 typedef std::tuple<_Tp*, _Dp> __tuple_type;
00263
00264 public:
00265 typedef _Tp* pointer;
00266 typedef _Tp element_type;
00267 typedef _Dp deleter_type;
00268
00269
00270 unique_ptr()
00271 : _M_t(pointer(), deleter_type())
00272 { static_assert(!std::is_pointer<deleter_type>::value,
00273 "constructed with null function pointer deleter"); }
00274
00275 explicit
00276 unique_ptr(pointer __p)
00277 : _M_t(__p, deleter_type())
00278 { static_assert(!std::is_pointer<deleter_type>::value,
00279 "constructed with null function pointer deleter"); }
00280
00281 unique_ptr(pointer __p,
00282 typename std::conditional<std::is_reference<deleter_type>::value,
00283 deleter_type, const deleter_type&>::type __d)
00284 : _M_t(__p, __d) { }
00285
00286 unique_ptr(pointer __p,
00287 typename std::remove_reference<deleter_type>::type && __d)
00288 : _M_t(std::move(__p), std::move(__d))
00289 { static_assert(!std::is_reference<deleter_type>::value,
00290 "rvalue deleter bound to reference"); }
00291
00292
00293 unique_ptr(nullptr_t)
00294 : _M_t(pointer(), deleter_type())
00295 { }
00296
00297
00298 unique_ptr(unique_ptr&& __u)
00299 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00300
00301 template<typename _Up, typename _Ep>
00302 unique_ptr(unique_ptr<_Up, _Ep>&& __u)
00303 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00304 { }
00305
00306
00307 ~unique_ptr() { reset(); }
00308
00309
00310 unique_ptr&
00311 operator=(unique_ptr&& __u)
00312 {
00313 reset(__u.release());
00314 get_deleter() = std::move(__u.get_deleter());
00315 return *this;
00316 }
00317
00318 template<typename _Up, typename _Ep>
00319 unique_ptr&
00320 operator=(unique_ptr<_Up, _Ep>&& __u)
00321 {
00322 reset(__u.release());
00323 get_deleter() = std::move(__u.get_deleter());
00324 return *this;
00325 }
00326
00327 unique_ptr&
00328 operator=(nullptr_t)
00329 {
00330 reset();
00331 return *this;
00332 }
00333
00334
00335 typename std::add_lvalue_reference<element_type>::type
00336 operator[](size_t __i) const
00337 {
00338 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00339 return get()[__i];
00340 }
00341
00342 pointer
00343 get() const
00344 { return std::get<0>(_M_t); }
00345
00346 deleter_type&
00347 get_deleter()
00348 { return std::get<1>(_M_t); }
00349
00350 const deleter_type&
00351 get_deleter() const
00352 { return std::get<1>(_M_t); }
00353
00354 explicit operator bool() const
00355 { return get() == pointer() ? false : true; }
00356
00357
00358 pointer
00359 release()
00360 {
00361 pointer __p = get();
00362 std::get<0>(_M_t) = pointer();
00363 return __p;
00364 }
00365
00366 void
00367 reset(pointer __p = pointer())
00368 {
00369 using std::swap;
00370 swap(std::get<0>(_M_t), __p);
00371 if (__p != nullptr)
00372 get_deleter()(__p);
00373 }
00374
00375 void
00376 reset(nullptr_t)
00377 {
00378 pointer __p = get();
00379 std::get<0>(_M_t) = pointer();
00380 if (__p != nullptr)
00381 get_deleter()(__p);
00382 }
00383
00384
00385 template<typename _Up>
00386 void reset(_Up) = delete;
00387
00388 void
00389 swap(unique_ptr& __u)
00390 {
00391 using std::swap;
00392 swap(_M_t, __u._M_t);
00393 }
00394
00395
00396 unique_ptr(const unique_ptr&) = delete;
00397 unique_ptr& operator=(const unique_ptr&) = delete;
00398
00399
00400
00401 template<typename _Up>
00402 unique_ptr(_Up*, typename
00403 std::conditional<std::is_reference<deleter_type>::value,
00404 deleter_type, const deleter_type&>::type,
00405 typename std::enable_if<std::is_convertible<_Up*,
00406 pointer>::value>::type* = 0) = delete;
00407
00408 template<typename _Up>
00409 unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
00410 typename std::enable_if<std::is_convertible<_Up*,
00411 pointer>::value>::type* = 0) = delete;
00412
00413 template<typename _Up>
00414 explicit
00415 unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
00416 pointer>::value>::type* = 0) = delete;
00417
00418 private:
00419 __tuple_type _M_t;
00420 };
00421
00422 template<typename _Tp, typename _Dp>
00423 inline void
00424 swap(unique_ptr<_Tp, _Dp>& __x,
00425 unique_ptr<_Tp, _Dp>& __y)
00426 { __x.swap(__y); }
00427
00428 template<typename _Tp, typename _Dp,
00429 typename _Up, typename _Ep>
00430 inline bool
00431 operator==(const unique_ptr<_Tp, _Dp>& __x,
00432 const unique_ptr<_Up, _Ep>& __y)
00433 { return __x.get() == __y.get(); }
00434
00435 template<typename _Tp, typename _Dp>
00436 inline bool
00437 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00438 { return __x.get() == nullptr; }
00439
00440 template<typename _Tp, typename _Dp>
00441 inline bool
00442 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
00443 { return nullptr == __y.get(); }
00444
00445 template<typename _Tp, typename _Dp,
00446 typename _Up, typename _Ep>
00447 inline bool
00448 operator!=(const unique_ptr<_Tp, _Dp>& __x,
00449 const unique_ptr<_Up, _Ep>& __y)
00450 { return !(__x.get() == __y.get()); }
00451
00452 template<typename _Tp, typename _Dp>
00453 inline bool
00454 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
00455 { return __x.get() != nullptr; }
00456
00457 template<typename _Tp, typename _Dp>
00458 inline bool
00459 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
00460 { return nullptr != __y.get(); }
00461
00462 template<typename _Tp, typename _Dp,
00463 typename _Up, typename _Ep>
00464 inline bool
00465 operator<(const unique_ptr<_Tp, _Dp>& __x,
00466 const unique_ptr<_Up, _Ep>& __y)
00467 { return __x.get() < __y.get(); }
00468
00469 template<typename _Tp, typename _Dp,
00470 typename _Up, typename _Ep>
00471 inline bool
00472 operator<=(const unique_ptr<_Tp, _Dp>& __x,
00473 const unique_ptr<_Up, _Ep>& __y)
00474 { return !(__y.get() < __x.get()); }
00475
00476 template<typename _Tp, typename _Dp,
00477 typename _Up, typename _Ep>
00478 inline bool
00479 operator>(const unique_ptr<_Tp, _Dp>& __x,
00480 const unique_ptr<_Up, _Ep>& __y)
00481 { return __y.get() < __x.get(); }
00482
00483 template<typename _Tp, typename _Dp,
00484 typename _Up, typename _Ep>
00485 inline bool
00486 operator>=(const unique_ptr<_Tp, _Dp>& __x,
00487 const unique_ptr<_Up, _Ep>& __y)
00488 { return !(__x.get() < __y.get()); }
00489
00490
00491 template<typename _Tp, typename _Dp>
00492 struct hash<unique_ptr<_Tp, _Dp>>
00493 : public std::unary_function<unique_ptr<_Tp, _Dp>, size_t>
00494 {
00495 size_t
00496 operator()(const unique_ptr<_Tp, _Dp>& __u) const
00497 {
00498 typedef unique_ptr<_Tp, _Dp> _UP;
00499 return std::hash<typename _UP::pointer>()(__u.get());
00500 }
00501 };
00502
00503
00504
00505 _GLIBCXX_END_NAMESPACE
00506
00507 #endif