unique_ptr.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2008 The FLWOR Foundation.
00003  * 
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  * 
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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>                      /* for unique_ptr */
00024 # include <utility>                     /* for forward, move */
00025 #else
00026 
00027 #include <algorithm>                    /* for swap() */
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  * \internal
00058  * Storage for unique_ptr's pointer and deleter.
00059  *
00060  * @tparam T The pointed-to type.
00061  * @tparam D The deleter type.
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   // forbid
00089   unique_ptr_storage( unique_ptr_storage const& );
00090   unique_ptr_storage& operator=( unique_ptr_storage const& );
00091 };
00092 
00093 /**
00094  * \internal
00095  * Specialization of %unique_ptr_storage when the \c D is empty.
00096  *
00097  * @tparam T The pointed-to type.
00098  * @tparam D The deleter type.
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   // forbid
00122   unique_ptr_storage( unique_ptr_storage const& );
00123   unique_ptr_storage& operator=( unique_ptr_storage const& );
00124 };
00125 
00126 ///////////////////////////////////////////////////////////////////////////////
00127 
00128 /**
00129  * \internal
00130  * Swaps two unique_ptr objects.
00131  *
00132  * @param a The first object to swap.
00133  * @param b The second object to swap.
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  * \internal
00146  * The default deleter class used by unique_ptr.  It simply calls \c delete on
00147  * the pointed-to object.
00148  */
00149 template<typename T>
00150 struct default_delete {
00151   default_delete() { }
00152 
00153   /**
00154    * Copy constructor.
00155    *
00156    * @tparam U The type of the deleter to copy-construct from such that \c U*
00157    * is convertible to \c T*.
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    * Deletes the pointed-to object using \c delete.
00167    *
00168    * @param p A pointer to the object to delete.
00169    */
00170   void operator()( T *p ) const {
00171     delete p;
00172   }
00173 };
00174 
00175 ///////////////////////////////////////////////////////////////////////////////
00176 
00177 /**
00178  * \internal
00179  * Emulation of the C++11 std::unique_ptr.
00180  *
00181  * @tparam T The pointed-to type.
00182  * @tparam D The deleter to use, if any.  It must be either a function pointer
00183  * or a functor such that if \c d is of type \a D and \c p is of type \a T*,
00184  * then \c d(p) is valid and deletes the pointed-to object.  The deleter must
00185  * handle null pointers.  Note that \a D may be a reference type.
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   // see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2333.html
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    * Default constructor.
00206    *
00207    * @param p A pointer to the object to point to, if any.
00208    */
00209   explicit unique_ptr( pointer p = 0 ) throw() : storage_( p ) {
00210   }
00211 
00212   /**
00213    * Constructs a %unique_ptr using a specific deleter.  This %unique_ptr now
00214    * has ownership of the pointed-to object.
00215    *
00216    * @param p A pointer to the object to own.
00217    * @param d The deleter to use.
00218    */
00219   unique_ptr( pointer p, deleter_reference d ) : storage_( p, d ) {
00220   }
00221 
00222   /**
00223    * Constructs a %unique_ptr from an existing %unique_ptr.  Note that:
00224    * \code
00225    *  unique_ptr<int> a( new int(1) );
00226    *  unique_ptr<int> b( a );           // compile-time error
00227    * \endcode
00228    * Instead, you must use the \c move() function:
00229    * \code
00230    *  unique_ptr<int> a( new int(1) );
00231    *  unique_ptr<int> b( move(a) );     // ok now
00232    * \endcode
00233    *
00234    * @param p The %unique_ptr to move from.
00235    */
00236   unique_ptr( zorba::internal::rv<unique_ptr> &p ) :
00237     storage_( p.release(), p.get_deleter() )
00238   {
00239   }
00240 
00241   /**
00242    * Constructs a %unique_ptr from an existing %unique_ptr 
00243    *
00244    * @tparam U The pointed-to type such that \c U* is convertible to \c T*.
00245    * @tparam E The deleter such that \c E is convertible to \c D.
00246    * @param p The %unique_ptr to move from.
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    * Destroys the pointed-to object by calling the deleter (if the pointer is
00265    * not null).
00266    */
00267   ~unique_ptr() {
00268     call_deleter();
00269   }
00270 
00271   /**
00272    * Destructive assignment: moves ownership of the object pointed-to by \a p
00273    * to this %unique_ptr.  The object pointed-to by this %unique_ptr, if any,
00274    * is deleted.
00275    *
00276    * @param p The %unique_ptr to move from.
00277    * @return Returns \c *this.
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    * Destructive assignment: moves ownership of the object pointed-to by \a p
00287    * to this %unique_ptr.  The object pointed-to by this %unique_ptr, if any,
00288    * is deleted.
00289    *
00290    * @tparam U The pointed-to type such that \c U* is convertible to \c T*.
00291    * @tparam E The deleter of \a p.
00292    * @param p The %unique_ptr to move from.
00293    * @return Returns \c *this.
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    * Assignment from null: equivalent to \c reset().
00304    *
00305    * @return Returns \c *this.
00306    */
00307   unique_ptr& operator=( int ) {
00308     reset();
00309     return *this;
00310   }
00311 
00312   /**
00313    * Dereferences the pointer.
00314    *
00315    * @return Returns a reference to the pointed-to object.
00316    */
00317   element_type& operator*() const throw() {
00318     return *get();
00319   }
00320 
00321   /**
00322    * Gets the pointer.
00323    *
00324    * @return Returns said pointer.
00325    */
00326   pointer operator->() const throw() {
00327     return get();
00328   }
00329 
00330   /**
00331    * Gets the pointer.
00332    *
00333    * @return Returns said pointer.
00334    */
00335   pointer get() const throw() {
00336     return storage_.ptr_;
00337   }
00338 
00339   /**
00340    * Gets the deleter in use.
00341    *
00342    * @return Returns said deleter.
00343    */
00344   deleter_reference get_deleter() throw() {
00345     return storage_.deleter();
00346   }
00347 
00348   /**
00349    * Gets the deleter in use.
00350    *
00351    * @return Returns said deleter.
00352    */
00353   deleter_const_reference get_deleter() const throw() {
00354     return storage_.deleter();
00355   }
00356 
00357   /**
00358    * Releases ownership of the pointed-to object.  Said object will now be the
00359    * responsibility of the caller.
00360    *
00361    * @return Returns a pointer to the object.
00362    */
00363   pointer release() throw() {
00364     pointer const temp = get();
00365     storage_.ptr_ = 0;
00366     return temp;
00367   }
00368 
00369   /**
00370    * Sets the pointer to the given value or null if none.  The previosly
00371    * pointed-to object, if any, is deleted.  However, if \a p equals the
00372    * current pointer value, then this function does nothing.
00373    *
00374    * @param p The new pointer value, if any.
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    * Swaps the pointer and deleter with that of another %unique_ptr.
00385    *
00386    * @param p The %unique_ptr to swap with.
00387    */
00388   void swap( unique_ptr &p ) {
00389     std::swap( storage_, p.storage_ );
00390   }
00391 
00392   /**
00393    * Conversion to \c bool.
00394    *
00395    * @return Returns \c true only if the pointer is not null; \c false only if
00396    * the pointer is null.
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   // forbid
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  * \internal
00447  * Swaps the pointed-to object and deleter of one unique_ptr with that of
00448  * another.
00449  *
00450  * @param a The first unique_ptr.
00451  * @param b The second unique_ptr.
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 } // namespace std
00461 
00462 #endif /* ZORBA_CXX_UNIQUE_PTR */
00463 #endif /* ZORBA_UNIQUE_PTR_H */
00464 /* vim:set et sw=2 ts=2: */
blog comments powered by Disqus