lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
cloneable_obj.h
00001 /*****************************************************/
00002 /* lean Smart                   (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_SMART_CLONEABLE_OBJ
00006 #define LEAN_SMART_CLONEABLE_OBJ
00007 
00008 #include "../cpp0x.h"
00009 #include "../meta/conditional.h"
00010 
00011 namespace lean
00012 {
00013 namespace smart
00014 {
00015 
00017 template <class Cloneable>
00018 LEAN_INLINE Cloneable* clone_cloneable(const Cloneable &cloneable)
00019 {
00020     return static_cast<Cloneable*>( cloneable.clone() );
00021 }
00023 template <class Cloneable>
00024 LEAN_INLINE void destroy_cloneable(Cloneable *cloneable)
00025 {
00026     if (cloneable)
00027         cloneable->destroy();
00028 }
00029 
00031 template <class Cloneable, bool PointerSemantics = false>
00032 class cloneable_obj
00033 {
00034 private:
00035     Cloneable *m_cloneable;
00036 
00038     static Cloneable* acquire(const Cloneable &cloneable)
00039     {
00040         return static_cast<Cloneable*>( clone_cloneable(cloneable) );
00041     }
00042 
00044     static Cloneable* acquire(const Cloneable *cloneable)
00045     {
00046         return (cloneable)
00047             ? acquire(*cloneable)
00048             : nullptr;
00049     }
00050 
00052     static void release(const Cloneable *cloneable)
00053     {
00054         destroy_cloneable(cloneable);
00055     }
00056 
00057 public:
00059     typedef Cloneable value_type;
00061     typedef typename conditional_type<PointerSemantics, value_type, const value_type>::type maybe_const_value_type;
00062 
00064     cloneable_obj(const value_type &cloneable)
00065         : m_cloneable( acquire(cloneable) ) { };
00067     cloneable_obj(const cloneable_obj &right)
00068         : m_cloneable( acquire(right.m_cloneable) ) { };
00070     cloneable_obj(const value_type *cloneable)
00071         : m_cloneable( acquire(cloneable) )
00072     {
00073         LEAN_STATIC_ASSERT_MSG_ALT(PointerSemantics,
00074             "Construction from pointer only available for pointer semantics.",
00075             Construction_from_pointer_only_available_for_pointer_semantics);
00076     }
00077 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00078 
00079     cloneable_obj(cloneable_obj &&right)
00080         : m_cloneable(std::move(right.m_cloneable))
00081     {
00082         // Warning: this "breaks" the other object
00083         right.m_cloneable = nullptr;
00084     }
00085 #endif
00086 
00087     ~cloneable_obj() throw()
00088     {
00089         release(m_cloneable);
00090     }
00091 
00093     static LEAN_INLINE cloneable_obj null()
00094     {
00095         LEAN_STATIC_ASSERT_MSG_ALT(PointerSemantics,
00096             "Null objects only available for pointer semantics.",
00097             Null_objects_only_available_for_pointer_semantics);
00098 
00099         // Warning: this object is effectively "broken"
00100         return cloneable_obj(nullptr);
00101     }
00102 
00104     cloneable_obj& operator =(const value_type &cloneable)
00105     {
00106         Cloneable *prevCloneable = m_cloneable;
00107         m_cloneable = acquire(cloneable);
00108         release(prevCloneable);
00109         
00110         return *this;
00111     }
00113     cloneable_obj& operator =(const value_type *cloneable)
00114     {
00115         LEAN_STATIC_ASSERT_MSG_ALT(PointerSemantics,
00116             "Pointer assignment only available for pointer semantics.",
00117             Pointer_assignment_only_available_for_pointer_semantics);
00118 
00119         Cloneable *prevCloneable = m_cloneable;
00120         m_cloneable = acquire(cloneable);
00121         release(prevCloneable);
00122         
00123         return *this;
00124     }
00126     cloneable_obj& operator =(const cloneable_obj &right)
00127     {
00128         if (m_cloneable != right.m_cloneable)
00129         {
00130             Cloneable *prevCloneable = m_cloneable;
00131             m_cloneable = acquire(right.m_cloneable);
00132             release(prevCloneable);
00133         }
00134         
00135         return *this;
00136     }
00137 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00138 
00139     cloneable_obj& operator =(cloneable_obj &&right)
00140     {
00141         if (m_cloneable != right.m_cloneable)
00142         {
00143             Cloneable *prevCloneable = m_cloneable;
00144             
00145             m_cloneable = std::move(right.m_cloneable);
00146             // Warning: this "breaks" the other object
00147             right.m_cloneable = nullptr;
00148 
00149             release(prevCloneable);
00150         }
00151         return *this;
00152     }
00153 #endif
00154 
00156     value_type& get(void) { LEAN_ASSERT(m_cloneable); return *m_cloneable; };
00158     maybe_const_value_type& get(void) const { LEAN_ASSERT(m_cloneable); return *m_cloneable; };
00160     value_type* getptr(void) { return m_cloneable; };
00162     maybe_const_value_type* getptr(void) const { return m_cloneable; };
00164     bool valid() const { return (m_cloneable != nullptr); };
00165 
00167     value_type& operator *() { return get(); };
00169     maybe_const_value_type& operator *() const { return get(); };
00171     value_type* operator ->() { LEAN_ASSERT(m_cloneable); return m_cloneable; };
00173     maybe_const_value_type* operator ->() const { LEAN_ASSERT(m_cloneable); return m_cloneable; };
00174 
00176     operator value_type&() { return get(); };
00178     operator maybe_const_value_type&() const { return get(); };
00179 };
00180 
00181 } // namespace
00182 
00183 using smart::cloneable_obj;
00184 
00185 } // namespace
00186 
00187 #endif