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