00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef ZORBA_UNIQUE_PTR_H
00018 #define ZORBA_UNIQUE_PTR_H
00019
00020 #include <zorba/config.h>
00021
00022 #ifdef ZORBA_CXX_UNIQUE_PTR
00023 # include <memory>
00024 # include <utility>
00025 #else
00026
00027 #include <algorithm>
00028 #include "type_traits.h"
00029
00030 namespace std {
00031
00032
00033
00034 template<typename T> inline
00035 typename enable_if<!zorba::internal::is_movable<T>::value,T&>::type
00036 move( T &t ) {
00037 return t;
00038 }
00039
00040 template<typename T> inline
00041 typename enable_if<zorba::internal::is_movable<T>::value,
00042 zorba::internal::rv<T>&>::type
00043 move( T &t ) {
00044 return *static_cast<zorba::internal::rv<T>*>( &t );
00045 }
00046
00047 template<typename T> inline
00048 typename enable_if<zorba::internal::is_movable<T>::value,
00049 zorba::internal::rv<T>&>::type
00050 move( zorba::internal::rv<T> &t ) {
00051 return t;
00052 }
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 template<typename T,typename D,bool = ZORBA_TR1_NS::is_empty<D>::value>
00064 class unique_ptr_storage {
00065 typedef typename ZORBA_TR1_NS::add_reference<D>::type deleter_reference;
00066 typedef zorba::internal::rv<unique_ptr_storage> rvalue_type;
00067 public:
00068 T *ptr_;
00069
00070 unique_ptr_storage( T *p ) throw() : ptr_( p ) {
00071 }
00072
00073 unique_ptr_storage( T *p, deleter_reference d ) :
00074 ptr_( p ), deleter_( d )
00075 {
00076 }
00077
00078 operator rvalue_type() throw() {
00079 return rvalue_type( *this );
00080 }
00081
00082 deleter_reference deleter() throw() {
00083 return deleter_;
00084 }
00085
00086 private:
00087 D deleter_;
00088
00089 unique_ptr_storage( unique_ptr_storage const& );
00090 unique_ptr_storage& operator=( unique_ptr_storage const& );
00091 };
00092
00093
00094
00095
00096
00097
00098
00099
00100 template<typename T,typename D>
00101 class unique_ptr_storage<T,D,true> : private D {
00102 typedef zorba::internal::rv<unique_ptr_storage> rvalue_type;
00103 public:
00104 T *ptr_;
00105
00106 unique_ptr_storage( T *p ) throw() : ptr_( p ) {
00107 }
00108
00109 unique_ptr_storage( T *p, D &d ) : D( d ), ptr_( p ) {
00110 }
00111
00112 operator rvalue_type() throw() {
00113 return rvalue_type( *this );
00114 }
00115
00116 D& deleter() throw() {
00117 return *this;
00118 }
00119
00120 private:
00121
00122 unique_ptr_storage( unique_ptr_storage const& );
00123 unique_ptr_storage& operator=( unique_ptr_storage const& );
00124 };
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 template<typename T,typename D,bool IsEmpty> inline
00136 void swap( unique_ptr_storage<T,D,IsEmpty> &a,
00137 unique_ptr_storage<T,D,IsEmpty> &b ) {
00138 std::swap( a.ptr_, b.ptr_ );
00139 std::swap( a.deleter(), b.deleter() );
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149 template<typename T>
00150 struct default_delete {
00151 default_delete() { }
00152
00153
00154
00155
00156
00157
00158
00159 template<typename U>
00160 default_delete( default_delete<U> const&,
00161 typename enable_if<ZORBA_TR1_NS::is_convertible<U*,T*>::value>::type* = 0 )
00162 {
00163 }
00164
00165
00166
00167
00168
00169
00170 void operator()( T *p ) const {
00171 delete p;
00172 }
00173 };
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 template<typename T,class D = default_delete<T> >
00188 class unique_ptr {
00189 typedef typename ZORBA_TR1_NS::add_reference<D>::type
00190 deleter_reference;
00191
00192 typedef typename ZORBA_TR1_NS::add_reference<D const>::type
00193 deleter_const_reference;
00194
00195
00196 struct pointer_conversion { int valid; };
00197 typedef int pointer_conversion::*explicit_bool;
00198
00199 public:
00200 typedef T element_type;
00201 typedef T* pointer;
00202 typedef D deleter_type;
00203
00204
00205
00206
00207
00208
00209 explicit unique_ptr( pointer p = 0 ) throw() : storage_( p ) {
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219 unique_ptr( pointer p, deleter_reference d ) : storage_( p, d ) {
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 unique_ptr( zorba::internal::rv<unique_ptr> &p ) :
00237 storage_( p.release(), p.get_deleter() )
00238 {
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 template<typename U,typename E>
00249 unique_ptr( zorba::internal::rv<unique_ptr<U,E> > &p,
00250 typename enable_if<
00251 ZORBA_TR1_NS::is_convertible<typename unique_ptr<U>::pointer,
00252 pointer>::value &&
00253 ZORBA_TR1_NS::is_convertible<E,D>::value && (
00254 !ZORBA_TR1_NS::is_reference<D>::value ||
00255 ZORBA_TR1_NS::is_same<D,E>::value
00256 )
00257 >::type* = 0
00258 ) :
00259 storage_( p.release(), move<D>( p.get_deleter() ) )
00260 {
00261 }
00262
00263
00264
00265
00266
00267 ~unique_ptr() {
00268 call_deleter();
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 unique_ptr& operator=( zorba::internal::rv<unique_ptr> &p ) {
00280 reset( p.release() );
00281 storage_.deleter() = move( p.get_deleter() );
00282 return *this;
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 template<typename U,typename E>
00296 unique_ptr& operator=( zorba::internal::rv<unique_ptr<U,E> > &p ) {
00297 reset( p.release() );
00298 storage_.deleter() = move( p.get_deleter() );
00299 return *this;
00300 }
00301
00302
00303
00304
00305
00306
00307 unique_ptr& operator=( int ) {
00308 reset();
00309 return *this;
00310 }
00311
00312
00313
00314
00315
00316
00317 element_type& operator*() const throw() {
00318 return *get();
00319 }
00320
00321
00322
00323
00324
00325
00326 pointer operator->() const throw() {
00327 return get();
00328 }
00329
00330
00331
00332
00333
00334
00335 pointer get() const throw() {
00336 return storage_.ptr_;
00337 }
00338
00339
00340
00341
00342
00343
00344 deleter_reference get_deleter() throw() {
00345 return storage_.deleter();
00346 }
00347
00348
00349
00350
00351
00352
00353 deleter_const_reference get_deleter() const throw() {
00354 return storage_.deleter();
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 pointer release() throw() {
00364 pointer const temp = get();
00365 storage_.ptr_ = 0;
00366 return temp;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376 void reset( pointer p = 0 ) throw() {
00377 if ( p != storage_.ptr_ ) {
00378 call_deleter();
00379 storage_.ptr_ = p;
00380 }
00381 }
00382
00383
00384
00385
00386
00387
00388 void swap( unique_ptr &p ) {
00389 std::swap( storage_, p.storage_ );
00390 }
00391
00392
00393
00394
00395
00396
00397
00398 operator explicit_bool() const throw() {
00399 return get() ? &pointer_conversion::valid : 0;
00400 }
00401
00402 private:
00403 unique_ptr_storage<T,D> storage_;
00404
00405 void call_deleter() {
00406 if ( storage_.ptr_ )
00407 get_deleter()( storage_.ptr_ );
00408 }
00409
00410
00411 unique_ptr( unique_ptr& );
00412 unique_ptr& operator=( unique_ptr& );
00413 template<typename U,typename E> unique_ptr( unique_ptr<U,E>& );
00414 template<typename U,typename E> unique_ptr& operator=( unique_ptr<U,E>& );
00415
00416 public:
00417 operator ::zorba::internal::rv<unique_ptr>&() throw() {
00418 return *static_cast<zorba::internal::rv<unique_ptr>*>( this );
00419 }
00420
00421 operator ::zorba::internal::rv<unique_ptr> const&() const throw() {
00422 return *static_cast<zorba::internal::rv<unique_ptr> const*>( this );
00423 }
00424 };
00425
00426
00427
00428 #define ZORBA_UNIQUE_PTR_RELOP(OP) \
00429 template<typename T1,typename D1,typename T2,typename D2> inline \
00430 bool operator OP( unique_ptr<T1,D1> const &a, unique_ptr<T2,D2> const &b ) { \
00431 return a.get() OP b.get(); \
00432 }
00433
00434 ZORBA_UNIQUE_PTR_RELOP(==)
00435 ZORBA_UNIQUE_PTR_RELOP(!=)
00436 ZORBA_UNIQUE_PTR_RELOP(< )
00437 ZORBA_UNIQUE_PTR_RELOP(<=)
00438 ZORBA_UNIQUE_PTR_RELOP(> )
00439 ZORBA_UNIQUE_PTR_RELOP(>=)
00440
00441 #undef ZORBA_UNIQUE_PTR_RELOP
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 template<typename T,typename D> inline
00454 void swap( unique_ptr<T,D> &a, unique_ptr<T,D> &b ) {
00455 a.swap( b );
00456 }
00457
00458
00459
00460 }
00461
00462 #endif
00463 #endif
00464