00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef UNIQUE_PTR_HPP
00017 #define UNIQUE_PTR_HPP
00018
00019 #include <boost/utility/enable_if.hpp>
00020 #include <boost/type_traits.hpp>
00021 #include <boost/static_assert.hpp>
00022 #include <boost/mpl/if.hpp>
00023
00024 namespace boost
00025 {
00026
00027 namespace detail_unique_ptr
00028 {
00029
00030 typedef char one;
00031 struct two {one _[2];};
00032
00033
00034
00035
00036
00037
00038 namespace is_conv_imp
00039 {
00040 template <class T> one test1(const T&);
00041 template <class T> two test1(...);
00042 template <class T> one test2(T);
00043 template <class T> two test2(...);
00044 template <class T> T source();
00045 }
00046
00047 template <class T1, class T2>
00048 struct is_convertible
00049 {
00050 static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1;
00051 };
00052
00053 template <class T>
00054 struct is_convertible<T, T>
00055 {
00056 static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1;
00057 };
00058
00059 template <class T>
00060 class rv
00061 {
00062 T& r_;
00063
00064 public:
00065 explicit rv(T& r) : r_(r) {}
00066 T* operator->() {return &r_;}
00067 T& operator*() {return r_;}
00068 };
00069
00070 template <class T>
00071 struct identity
00072 {
00073 typedef T type;
00074 };
00075
00076 }
00077
00078 template <class T>
00079 inline
00080 typename enable_if_c
00081 <
00082 !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value,
00083 T&
00084 >::type
00085 move(T& t)
00086 {
00087 return t;
00088 }
00089
00090 template <class T>
00091 inline
00092 typename enable_if_c
00093 <
00094 !detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value,
00095 const T&
00096 >::type
00097 move(const T& t)
00098 {
00099 return t;
00100 }
00101
00102 template <class T>
00103 inline
00104 typename enable_if_c
00105 <
00106 detail_unique_ptr::is_convertible<T, detail_unique_ptr::rv<T> >::value,
00107 T
00108 >::type
00109 move(T& t)
00110 {
00111 return T(detail_unique_ptr::rv<T>(t));
00112 }
00113
00114 template <class T>
00115 inline
00116 typename enable_if_c
00117 <
00118 is_reference<T>::value,
00119 T
00120 >::type
00121 forward(typename detail_unique_ptr::identity<T>::type t)
00122 {
00123 return t;
00124 }
00125
00126 template <class T>
00127 inline
00128 typename enable_if_c
00129 <
00130 !is_reference<T>::value,
00131 T
00132 >::type
00133 forward(typename detail_unique_ptr::identity<T>::type& t)
00134 {
00135 return move(t);
00136 }
00137
00138 template <class T>
00139 inline
00140 typename enable_if_c
00141 <
00142 !is_reference<T>::value,
00143 T
00144 >::type
00145 forward(const typename detail_unique_ptr::identity<T>::type& t)
00146 {
00147 return move(const_cast<T&>(t));
00148 }
00149
00150 namespace detail_unique_ptr {
00151
00152
00153 template <class T1, class T2, bool = is_empty<T2>::value>
00154 class unique_ptr_storage
00155 {
00156 T1 t1_;
00157 T2 t2_;
00158
00159 typedef typename add_reference<T2>::type T2_reference;
00160 typedef typename add_reference<const T2>::type T2_const_reference;
00161
00162 unique_ptr_storage(const unique_ptr_storage&);
00163 unique_ptr_storage& operator=(const unique_ptr_storage&);
00164 public:
00165 operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);}
00166
00167 unique_ptr_storage() : t1_(), t2_() {}
00168
00169 explicit unique_ptr_storage(T1 t1)
00170 : t1_(move(t1)), t2_() {}
00171
00172 unique_ptr_storage(T1 t1, T2 t2)
00173 : t1_(move(t1)), t2_(forward<T2>(t2)) {}
00174
00175 T1& first() {return t1_;}
00176 const T1& first() const {return t1_;}
00177
00178 T2_reference second() {return t2_;}
00179 T2_const_reference second() const {return t2_;}
00180 };
00181
00182 template <class T1, class T2>
00183 class unique_ptr_storage<T1, T2, true>
00184 : private T2
00185 {
00186 T1 t1_;
00187 typedef T2 t2_;
00188
00189 unique_ptr_storage(const unique_ptr_storage&);
00190 unique_ptr_storage& operator=(const unique_ptr_storage&);
00191 public:
00192 operator rv<unique_ptr_storage>() {return rv<unique_ptr_storage>(*this);}
00193
00194 unique_ptr_storage() : t1_() {}
00195
00196 explicit unique_ptr_storage(T1 t1)
00197 : t1_(move(t1)) {}
00198
00199 unique_ptr_storage(T1 t1, T2 t2)
00200 : t2_(move(t2)), t1_(move(t1)) {}
00201
00202 T1& first() {return t1_;}
00203 const T1& first() const {return t1_;}
00204
00205 T2& second() {return *this;}
00206 const T2& second() const {return *this;}
00207 };
00208
00209 template <class T1, class T2, bool b>
00210 inline
00211 void
00212 swap(unique_ptr_storage<T1, T2, b>& x, unique_ptr_storage<T1, T2, b>& y)
00213 {
00214 using std::swap;
00215 swap(x.first(), y.first());
00216 swap(x.second(), y.second());
00217 }
00218
00219 }
00220
00221 template <class T>
00222 struct default_delete
00223 {
00224 default_delete() {}
00225 template <class U>
00226 default_delete(const default_delete<U>&,
00227 typename enable_if_c<detail_unique_ptr::is_convertible<U*, T*>::value>::type* = 0)
00228 {}
00229
00230 void operator()(T* ptr) const
00231 {
00232 BOOST_STATIC_ASSERT(sizeof(T) > 0);
00233 delete ptr;
00234 }
00235 };
00236
00237 template <class T>
00238 struct default_delete<T[]>
00239 {
00240 void operator()(T* ptr) const
00241 {
00242 BOOST_STATIC_ASSERT(sizeof(T) > 0);
00243 delete [] ptr;
00244 }
00245
00246 private:
00247
00248 template <class U> void operator()(U*) const;
00249 };
00250
00251 namespace detail_unique_ptr
00252 {
00253
00254 namespace pointer_type_imp
00255 {
00256
00257 template <class U> static two test(...);
00258 template <class U> static one test(typename U::pointer* = 0);
00259
00260 }
00261
00262 template <class T>
00263 struct has_pointer_type
00264 {
00265 static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
00266 };
00267
00268 namespace pointer_type_imp
00269 {
00270
00271 template <class T, class D, bool = has_pointer_type<D>::value>
00272 struct pointer_type
00273 {
00274 typedef typename D::pointer type;
00275 };
00276
00277 template <class T, class D>
00278 struct pointer_type<T, D, false>
00279 {
00280 typedef T* type;
00281 };
00282
00283 }
00284
00285 template <class T, class D>
00286 struct pointer_type
00287 {
00288 typedef typename pointer_type_imp::pointer_type<T,
00289 typename boost::remove_reference<D>::type>::type type;
00290 };
00291
00292 }
00293
00294 template <class T, class D = default_delete<T> >
00295 class unique_ptr
00296 {
00297 public:
00298 typedef T element_type;
00299 typedef D deleter_type;
00300 typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer;
00301
00302 private:
00303 detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_;
00304
00305 typedef typename add_reference<deleter_type>::type deleter_reference;
00306 typedef typename add_reference<const deleter_type>::type deleter_const_reference;
00307
00308 struct nat {int for_bool_;};
00309
00310 unique_ptr(unique_ptr&);
00311 unique_ptr& operator=(unique_ptr&);
00312
00313 public:
00314 operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);}
00315 unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {}
00316 unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r)
00317 {
00318 reset(r->release());
00319 ptr_.second() = move(r->get_deleter());
00320 return *this;
00321 }
00322
00323 unique_ptr()
00324 {
00325 BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
00326 BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
00327 }
00328
00329 explicit unique_ptr(pointer p)
00330 : ptr_(p)
00331 {
00332 BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
00333 BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
00334 }
00335
00336 unique_ptr(pointer p, typename mpl::if_<is_reference<D>,
00337 volatile typename remove_reference<D>::type&, D>::type d)
00338 : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {}
00339
00340 template <class U, class E>
00341 unique_ptr(unique_ptr<U, E> u,
00342 typename enable_if_c
00343 <
00344 !boost::is_array<U>::value &&
00345 detail_unique_ptr::is_convertible<typename unique_ptr<U>::pointer, pointer>::value &&
00346 detail_unique_ptr::is_convertible<E, deleter_type>::value &&
00347 (
00348 !is_reference<deleter_type>::value ||
00349 is_same<deleter_type, E>::value
00350 )
00351 >::type* = 0)
00352 : ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {}
00353
00354 ~unique_ptr() {reset();}
00355
00356 unique_ptr& operator=(int nat::*)
00357 {
00358 reset();
00359 return *this;
00360 }
00361
00362 template <class U, class E>
00363 unique_ptr&
00364 operator=(unique_ptr<U, E> u)
00365 {
00366 reset(u.release());
00367 ptr_.second() = move(u.get_deleter());
00368 return *this;
00369 }
00370
00371 typename add_reference<T>::type operator*() const {return *get();}
00372 pointer operator->() const {return get();}
00373 pointer get() const {return ptr_.first();}
00374 deleter_reference get_deleter() {return ptr_.second();}
00375 deleter_const_reference get_deleter() const {return ptr_.second();}
00376 operator int nat::*() const {return get() ? &nat::for_bool_ : 0;}
00377
00378 void reset(pointer p = pointer())
00379 {
00380 pointer t = get();
00381 if (t != pointer())
00382 get_deleter()(t);
00383 ptr_.first() = p;
00384 }
00385
00386 pointer release()
00387 {
00388 pointer tmp = get();
00389 ptr_.first() = pointer();
00390 return tmp;
00391 }
00392
00393 void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);}
00394 };
00395
00396 template <class T, class D>
00397 class unique_ptr<T[], D>
00398 {
00399 public:
00400 typedef T element_type;
00401 typedef D deleter_type;
00402 typedef typename detail_unique_ptr::pointer_type<element_type, deleter_type>::type pointer;
00403
00404 private:
00405 detail_unique_ptr::unique_ptr_storage<pointer, deleter_type> ptr_;
00406
00407 typedef typename add_reference<deleter_type>::type deleter_reference;
00408 typedef typename add_reference<const deleter_type>::type deleter_const_reference;
00409
00410 struct nat {int for_bool_;};
00411
00412 unique_ptr(unique_ptr&);
00413 unique_ptr& operator=(unique_ptr&);
00414
00415 public:
00416 operator detail_unique_ptr::rv<unique_ptr>() {return detail_unique_ptr::rv<unique_ptr>(*this);}
00417 unique_ptr(detail_unique_ptr::rv<unique_ptr> r) : ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {}
00418 unique_ptr& operator=(detail_unique_ptr::rv<unique_ptr> r)
00419 {
00420 reset(r->release());
00421 ptr_.second() = move(r->get_deleter());
00422 return *this;
00423 }
00424
00425 unique_ptr()
00426 {
00427 BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
00428 BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
00429 }
00430
00431 explicit unique_ptr(pointer p)
00432 : ptr_(p)
00433 {
00434 BOOST_STATIC_ASSERT(!is_reference<deleter_type>::value);
00435 BOOST_STATIC_ASSERT(!is_pointer<deleter_type>::value);
00436 }
00437
00438 unique_ptr(pointer p, typename mpl::if_<is_reference<D>,
00439 volatile typename remove_reference<D>::type&, D>::type d)
00440 : ptr_(move(p), forward<D>(const_cast<typename add_reference<D>::type>(d))) {}
00441
00442 ~unique_ptr() {reset();}
00443
00444 T& operator[](size_t i) const {return get()[i];}
00445 pointer get() const {return ptr_.first();}
00446 deleter_reference get_deleter() {return ptr_.second();}
00447 deleter_const_reference get_deleter() const {return ptr_.second();}
00448 operator int nat::*() const {return get() ? &nat::for_bool_ : 0;}
00449
00450 void reset(pointer p = pointer())
00451 {
00452 pointer t = get();
00453 if (t != pointer())
00454 get_deleter()(t);
00455 ptr_.first() = p;
00456 }
00457
00458 pointer release()
00459 {
00460 pointer tmp = get();
00461 ptr_.first() = pointer();
00462 return tmp;
00463 }
00464
00465 void swap(unique_ptr& u) {detail_unique_ptr::swap(ptr_, u.ptr_);}
00466 private:
00467 template <class U>
00468 explicit unique_ptr(U,
00469 typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0);
00470
00471 template <class U>
00472 unique_ptr(U, typename mpl::if_<is_reference<D>,
00473 volatile typename remove_reference<D>::type&, D>::type,
00474 typename enable_if_c<detail_unique_ptr::is_convertible<U, pointer>::value>::type* = 0);
00475 };
00476
00477 template<class T, class D>
00478 inline
00479 void
00480 swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y)
00481 {
00482 x.swap(y);
00483 }
00484
00485 template<class T1, class D1, class T2, class D2>
00486 inline
00487 bool
00488 operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
00489 {
00490 return x.get() == y.get();
00491 }
00492
00493 template<class T1, class D1, class T2, class D2>
00494 inline
00495 bool
00496 operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
00497 {
00498 return !(x == y);
00499 }
00500
00501 template<class T1, class D1, class T2, class D2>
00502 inline
00503 bool
00504 operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
00505 {
00506 return x.get() < y.get();
00507 }
00508
00509 template<class T1, class D1, class T2, class D2>
00510 inline
00511 bool
00512 operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
00513 {
00514 return !(y < x);
00515 }
00516
00517 template<class T1, class D1, class T2, class D2>
00518 inline
00519 bool
00520 operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
00521 {
00522 return y < x;
00523 }
00524
00525 template<class T1, class D1, class T2, class D2>
00526 inline
00527 bool
00528 operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
00529 {
00530 return !(x < y);
00531 }
00532
00533 }
00534
00535 #endif // UNIQUE_PTR_HPP