lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
scoped_ptr.h
00001 /*****************************************************/
00002 /* lean Smart                   (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_SMART_SCOPED_PTR
00006 #define LEAN_SMART_SCOPED_PTR
00007 
00008 #include "../lean.h"
00009 #include "../tags/noncopyable.h"
00010 #include "../meta/dependent_false.h"
00011 #include "../meta/strip.h"
00012 
00013 namespace lean
00014 {
00015 namespace smart
00016 {
00017 
00019 template <class Type>
00020 LEAN_INLINE void release_ptr(Type *object)
00021 {
00022     if (sizeof(Type) > 0)
00023         delete object;
00024 }
00025 
00027 template <class Type>
00028 LEAN_INLINE void release_array_ptr(Type *object)
00029 {
00030     if (sizeof(Type) > 0)
00031         delete[] object;
00032 }
00033 
00035 template <class Type>
00036 struct generic_ptr_policy
00037 {
00039     static LEAN_INLINE void release(Type *object)
00040     {
00041         release_ptr(object);
00042     }
00043 };
00044 template <class Type>
00045 struct generic_ptr_policy<Type[]>
00046 {
00047     static LEAN_INLINE void release(Type *object)
00048     {
00049         release_array_ptr(object);
00050     }
00051 };
00052 
00054 template <class Type>
00055 struct delete_ptr_policy
00056 {
00058     static LEAN_INLINE void release(Type *object)
00059     {
00060         if (sizeof(Type) > 0)
00061             delete object;
00062     }
00063 };
00064 template <class Type>
00065 struct delete_ptr_policy<Type[]>
00066 {
00067     static LEAN_INLINE void release(Type *object)
00068     {
00069         if (sizeof(Type) > 0)
00070             delete[] object;
00071     }
00072 };
00073 
00075 template <class Type>
00076 struct destroy_ptr_policy
00077 {
00079     static LEAN_INLINE void release(Type *object)
00080     {
00081         if (object)
00082             object->destroy();
00083     }
00084 };
00085 template <class Type>
00086 struct destroy_ptr_policy<Type[]>;
00087 
00089 template <class Type>
00090 struct release_ptr_policy
00091 {
00093     static LEAN_INLINE void release(Type *object)
00094     {
00095         if (object)
00096             object->release();
00097     }
00098 };
00099 template <class Type>
00100 struct release_ptr_policy<Type[]>;
00101 
00103 template < class Type, class ReleasePolicy = generic_ptr_policy<Type> >
00104 class scoped_ptr : public noncopyable
00105 {
00106 public:
00108     typedef typename lean::strip_array<Type>::type object_type;
00110     typedef object_type* value_type;
00111 
00112 private:
00113     value_type m_object;
00114 
00115 public:
00117     explicit scoped_ptr(object_type *object = nullptr)
00118         : m_object( object ) { };
00120     template <class Type2>
00121     explicit scoped_ptr(Type2 *object)
00122         : m_object( object ) { };
00123 
00124 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00125 
00126     template <class Type2>
00127     scoped_ptr(scoped_ptr<Type2> &&right)
00128         : m_object( right.detatch() ) { }
00129 #endif
00130     
00132     LEAN_INLINE ~scoped_ptr()
00133     {
00134         ReleasePolicy::release(m_object);
00135     }
00136 
00138     LEAN_INLINE object_type* detatch()
00139     {
00140         value_type prevObject = m_object;
00141         m_object = nullptr;
00142         return prevObject;
00143     }
00144 
00146     scoped_ptr& operator =(object_type *object)
00147     {
00148         // Self-assignment would be wrong
00149         if(object != m_object)
00150         {
00151             value_type prevObject = m_object;
00152             m_object = object;
00153             ReleasePolicy::release(prevObject);
00154         }
00155         
00156         return *this;
00157     }
00158 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00159 
00160     template <class Type2>
00161     scoped_ptr& operator =(scoped_ptr<Type2> &&right)
00162     {
00163         // Self-assignment would be wrong
00164         if (addressof(right) != static_cast<void*>(this))
00165         {
00166             value_type prevObject = m_object;
00167             m_object = right.detatch();
00168             ReleasePolicy::release(prevObject);
00169         }
00170 
00171         return *this;
00172     }
00173 #endif
00174 
00176     LEAN_INLINE object_type*const& get() const { return m_object; }
00177 
00179     LEAN_INLINE object_type& operator *() const { return *get(); }
00181     LEAN_INLINE object_type* operator ->() const { return get(); }
00182 
00184     LEAN_INLINE operator object_type*() const { return get(); }
00185 };
00186 
00187 } // namespace
00188 
00189 using smart::scoped_ptr;
00190 
00191 } // namespace
00192 
00193 #endif