lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean PImpl (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_PIMPL_PIMPL_PTR 00006 #define LEAN_PIMPL_PIMPL_PTR 00007 00008 #include "../tags/noncopyable.h" 00009 00010 namespace lean 00011 { 00012 namespace pimpl 00013 { 00014 00016 struct pimpl_delete_policy 00017 { 00019 template <class Implementation> 00020 static void destroy(Implementation *impl) 00021 { 00022 if (sizeof(Implementation) > 0) 00023 delete impl; 00024 } 00025 }; 00026 00028 template <class Implementation, class ImplementationBase = Implementation, class DestroyPolicy = pimpl_delete_policy> 00029 class pimpl_ptr : public noncopyable 00030 { 00031 private: 00032 ImplementationBase *m_impl; 00033 00035 static LEAN_INLINE void delete_impl(const ImplementationBase *impl) 00036 { 00037 // Check, if implementation class fully defined 00038 delete_full_impl( impl, static_cast<const Implementation*>(nullptr) ); 00039 } 00041 static LEAN_INLINE void delete_full_impl(const ImplementationBase *base, const ImplementationBase*) 00042 { 00043 // Overload resolution suggests that implementation class is fully defined 00044 DestroyPolicy::destroy( static_cast<const Implementation*>(base) ); 00045 } 00047 static LEAN_INLINE void delete_full_impl(const ImplementationBase *base, const void*) 00048 { 00049 // Overload resolution suggests that implementation definition is incomplete 00050 DestroyPolicy::destroy( base ); 00051 } 00052 00053 public: 00055 typedef Implementation implementation_type; 00057 typedef ImplementationBase base_type; 00058 00060 LEAN_INLINE pimpl_ptr(Implementation *impl) 00061 : m_impl(impl) { } 00063 LEAN_INLINE pimpl_ptr(pimpl_ptr &&right) 00064 : m_impl(right.m_impl) 00065 { 00066 right.m_impl = nullptr; 00067 } 00069 LEAN_INLINE ~pimpl_ptr() throw() 00070 { 00071 delete_impl(m_impl); 00072 } 00073 00075 pimpl_ptr& operator =(Implementation *impl) 00076 { 00077 if (impl != m_impl) 00078 { 00079 ImplementationBase *prevImpl = m_impl; 00080 m_impl = impl; 00081 delete_impl(prevImpl); 00082 } 00083 00084 return *this; 00085 } 00087 pimpl_ptr& operator =(pimpl_ptr &&right) 00088 { 00089 if (right.m_impl != m_impl) 00090 { 00091 ImplementationBase *prevImpl = m_impl; 00092 00093 m_impl = right.m_impl; 00094 right.m_impl = nullptr; 00095 00096 delete_impl(prevImpl); 00097 } 00098 return *this; 00099 } 00100 00102 Implementation* unbind() 00103 { 00104 Implementation *impl = getptr(); 00105 m_impl = nullptr; 00106 return impl; 00107 } 00108 00110 LEAN_INLINE Implementation* getptr(void) { return static_cast<Implementation*>(m_impl); } 00112 LEAN_INLINE const Implementation* getptr(void) const { return static_cast<const Implementation*>(m_impl); } 00114 LEAN_INLINE Implementation& get(void) { return *getptr(); } 00116 LEAN_INLINE const Implementation& get(void) const { return *getptr(); } 00117 00119 LEAN_INLINE bool empty(void) { return (m_impl == nullptr); } 00120 00122 LEAN_INLINE Implementation& operator *() { return get(); } 00124 LEAN_INLINE const Implementation& operator *() const { return get(); } 00126 LEAN_INLINE Implementation* operator ->() { return getptr(); } 00128 LEAN_INLINE const Implementation* operator ->() const { return getptr(); } 00129 }; 00130 00131 } // namespace 00132 00133 using pimpl::pimpl_ptr; 00134 00135 } // namespace 00136 00137 #endif