lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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