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 const &t ) {
00044 return *static_cast<zorba::internal::rv<T>*>( const_cast<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 template<typename T>
00181 struct default_delete<T[]> {
00182 default_delete() { }
00183 void operator()( T *p ) const {
00184 delete[] p;
00185 }
00186 };
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 template<typename T,class D = default_delete<T> >
00201 class unique_ptr {
00202 typedef typename ZORBA_TR1_NS::add_reference<D>::type
00203 deleter_reference;
00204
00205 typedef typename ZORBA_TR1_NS::add_reference<D const>::type
00206 deleter_const_reference;
00207
00208
00209 struct pointer_conversion { int valid; };
00210 typedef int pointer_conversion::*explicit_bool;
00211
00212 public:
00213 typedef T element_type;
00214 typedef T* pointer;
00215 typedef D deleter_type;
00216
00217
00218
00219
00220
00221
00222 explicit unique_ptr( pointer p = 0 ) throw() : storage_( p ) {
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 unique_ptr( pointer p, deleter_reference d ) : storage_( p, d ) {
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 unique_ptr( zorba::internal::rv<unique_ptr> &p ) :
00250 storage_( p.release(), p.get_deleter() )
00251 {
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261 template<typename U,typename E>
00262 unique_ptr( zorba::internal::rv<unique_ptr<U,E> > &p,
00263 typename enable_if<
00264 ZORBA_TR1_NS::is_convertible<typename unique_ptr<U>::pointer,
00265 pointer>::value &&
00266 ZORBA_TR1_NS::is_convertible<E,D>::value && (
00267 !ZORBA_TR1_NS::is_reference<D>::value ||
00268 ZORBA_TR1_NS::is_same<D,E>::value
00269 )
00270 >::type* = 0
00271 ) :
00272 storage_( p.release(), move<D>( p.get_deleter() ) )
00273 {
00274 }
00275
00276
00277
00278
00279
00280 ~unique_ptr() {
00281 call_deleter();
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 unique_ptr& operator=( zorba::internal::rv<unique_ptr> &p ) {
00293 reset( p.release() );
00294 storage_.deleter() = move( p.get_deleter() );
00295 return *this;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 template<typename U,typename E>
00309 unique_ptr& operator=( zorba::internal::rv<unique_ptr<U,E> > &p ) {
00310 reset( p.release() );
00311 storage_.deleter() = move( p.get_deleter() );
00312 return *this;
00313 }
00314
00315
00316
00317
00318
00319
00320 unique_ptr& operator=( int ) {
00321 reset();
00322 return *this;
00323 }
00324
00325
00326
00327
00328
00329
00330 element_type& operator*() const throw() {
00331 return *get();
00332 }
00333
00334
00335
00336
00337
00338
00339 pointer operator->() const throw() {
00340 return get();
00341 }
00342
00343
00344
00345
00346
00347
00348 pointer get() const throw() {
00349 return storage_.ptr_;
00350 }
00351
00352
00353
00354
00355
00356
00357 deleter_reference get_deleter() throw() {
00358 return storage_.deleter();
00359 }
00360
00361
00362
00363
00364
00365
00366 deleter_const_reference get_deleter() const throw() {
00367 return storage_.deleter();
00368 }
00369
00370
00371
00372
00373
00374
00375
00376 pointer release() throw() {
00377 pointer const temp = get();
00378 storage_.ptr_ = 0;
00379 return temp;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 void reset( pointer p = 0 ) throw() {
00390 if ( p != storage_.ptr_ ) {
00391 call_deleter();
00392 storage_.ptr_ = p;
00393 }
00394 }
00395
00396
00397
00398
00399
00400
00401 void swap( unique_ptr &p ) {
00402 std::swap( storage_, p.storage_ );
00403 }
00404
00405
00406
00407
00408
00409
00410
00411 operator explicit_bool() const throw() {
00412 return get() ? &pointer_conversion::valid : 0;
00413 }
00414
00415 private:
00416 unique_ptr_storage<T,D> storage_;
00417
00418 void call_deleter() {
00419 if ( storage_.ptr_ )
00420 get_deleter()( storage_.ptr_ );
00421 }
00422
00423
00424 unique_ptr( unique_ptr& );
00425 unique_ptr& operator=( unique_ptr& );
00426 template<typename U,typename E> unique_ptr( unique_ptr<U,E>& );
00427 template<typename U,typename E> unique_ptr& operator=( unique_ptr<U,E>& );
00428
00429 public:
00430 operator ::zorba::internal::rv<unique_ptr>&() throw() {
00431 return *static_cast<zorba::internal::rv<unique_ptr>*>( this );
00432 }
00433
00434 operator ::zorba::internal::rv<unique_ptr> const&() const throw() {
00435 return *static_cast<zorba::internal::rv<unique_ptr> const*>( this );
00436 }
00437 };
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 template<typename T,typename D>
00452 class unique_ptr<T[],D> {
00453 typedef typename ZORBA_TR1_NS::add_reference<D>::type
00454 deleter_reference;
00455
00456 typedef typename ZORBA_TR1_NS::add_reference<D const>::type
00457 deleter_const_reference;
00458
00459 struct pointer_conversion { int valid; };
00460 typedef int pointer_conversion::*explicit_bool;
00461
00462 public:
00463 typedef T element_type;
00464 typedef T* pointer;
00465 typedef D deleter_type;
00466
00467 explicit unique_ptr( pointer p = 0 ) throw() : storage_( p ) {
00468 }
00469
00470 unique_ptr( pointer p, deleter_reference d ) : storage_( p, d ) {
00471 }
00472
00473 ~unique_ptr() {
00474 call_deleter();
00475 }
00476
00477 unique_ptr& operator=( zorba::internal::rv<unique_ptr> &p ) {
00478 reset( p.release() );
00479 storage_.deleter() = move( p.get_deleter() );
00480 return *this;
00481 }
00482
00483 pointer get() const throw() {
00484 return storage_.ptr_;
00485 }
00486
00487 T& operator[]( size_t i ) const {
00488 return get()[i];
00489 }
00490
00491 deleter_reference get_deleter() throw() {
00492 return storage_.deleter();
00493 }
00494
00495 deleter_const_reference get_deleter() const throw() {
00496 return storage_.deleter();
00497 }
00498
00499 pointer release() throw() {
00500 pointer const temp = get();
00501 storage_.ptr_ = 0;
00502 return temp;
00503 }
00504
00505 void reset( pointer p = 0 ) throw() {
00506 if ( p != storage_.ptr_ ) {
00507 call_deleter();
00508 storage_.ptr_ = p;
00509 }
00510 }
00511
00512 void swap( unique_ptr &p ) {
00513 std::swap( storage_, p.storage_ );
00514 }
00515
00516 operator explicit_bool() const throw() {
00517 return get() ? &pointer_conversion::valid : 0;
00518 }
00519
00520 private:
00521 unique_ptr_storage<T,D> storage_;
00522
00523 void call_deleter() {
00524 if ( storage_.ptr_ )
00525 get_deleter()( storage_.ptr_ );
00526 }
00527
00528
00529 unique_ptr( unique_ptr& );
00530 unique_ptr& operator=( unique_ptr& );
00531 template<typename U,typename E> unique_ptr( unique_ptr<U,E>& );
00532 template<typename U,typename E> unique_ptr& operator=( unique_ptr<U,E>& );
00533
00534 public:
00535 operator ::zorba::internal::rv<unique_ptr>&() throw() {
00536 return *static_cast<zorba::internal::rv<unique_ptr>*>( this );
00537 }
00538
00539 operator ::zorba::internal::rv<unique_ptr> const&() const throw() {
00540 return *static_cast<zorba::internal::rv<unique_ptr> const*>( this );
00541 }
00542 };
00543
00544
00545
00546 #define ZORBA_UNIQUE_PTR_RELOP(OP) \
00547 template<typename T1,typename D1,typename T2,typename D2> inline \
00548 bool operator OP( unique_ptr<T1,D1> const &a, unique_ptr<T2,D2> const &b ) { \
00549 return a.get() OP b.get(); \
00550 }
00551
00552 ZORBA_UNIQUE_PTR_RELOP(==)
00553 ZORBA_UNIQUE_PTR_RELOP(!=)
00554 ZORBA_UNIQUE_PTR_RELOP(< )
00555 ZORBA_UNIQUE_PTR_RELOP(<=)
00556 ZORBA_UNIQUE_PTR_RELOP(> )
00557 ZORBA_UNIQUE_PTR_RELOP(>=)
00558
00559 #undef ZORBA_UNIQUE_PTR_RELOP
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 template<typename T,typename D> inline
00572 void swap( unique_ptr<T,D> &a, unique_ptr<T,D> &b ) {
00573 a.swap( b );
00574 }
00575
00576
00577
00578 }
00579
00580 #endif
00581 #endif
00582