From 264e2050300608e09669b15e6facd329c604c1ee Mon Sep 17 00:00:00 2001 From: syntheticpp Date: Sun, 15 Jan 2006 22:03:10 +0000 Subject: [PATCH] add pimple/rimpl idiom git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@471 7ec92016-0320-0410-acc4-a06ded1c099a --- include/loki/Pimpl.h | 272 ++++++++++++++++++++++++++++++++++++++++ include/loki/PimplDef.h | 70 +++++++++++ 2 files changed, 342 insertions(+) create mode 100755 include/loki/Pimpl.h create mode 100755 include/loki/PimplDef.h diff --git a/include/loki/Pimpl.h b/include/loki/Pimpl.h new file mode 100755 index 0000000..e8d34c5 --- /dev/null +++ b/include/loki/Pimpl.h @@ -0,0 +1,272 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_PIMPL_H +#define LOKI_PIMPL_H + +#include + + +#ifndef LOKI_INHERITED_PIMPL_NAME +#define LOKI_INHERITED_PIMPL_NAME pimpl +#endif + +#ifndef LOKI_INHERITED_RIMPL_NAME +#define LOKI_INHERITED_RIMPL_NAME rimpl +#endif + +namespace Loki +{ + template + struct Impl; + + + ///////////////////// + // creation policies + ///////////////////// + // hard coded creation prefered + + + ///////////////////// + // destroy policies + ///////////////////// + template + struct AutoDeletePimpl + { + static void Destroy(T ptr) + { + typedef char T_must_be_defined[ + sizeof(typename TypeTraits::PointeeType) ? 1 : -1 ]; + delete ptr; + ptr = 0; + } + }; + + template + struct DontDeletePimpl + { + static void Destroy(T) + {} + }; + + + ///////////////////// + // Lifetime manager + ///////////////////// + + template + < + class Impl, + class Ptr, + template class Del + > + struct PimplLife + { + PimplLife(); + ~PimplLife(); + + template + operator T&(); + + Ptr Create(); + + Ptr ptr; + }; + + + namespace Private + { + template + struct HaveAPimplLife + { + T life; + }; + } + + + + ///////////////////// + // Pimpl usage policies + ///////////////////// + + template class Del> + class DeclaredPimpl : private Private::HaveAPimplLife > + { + typedef Private::HaveAPimplLife > Life; + + public: + Ptr operator->() const + { + return ptr; + } + + Impl& operator*() const + { + return *ptr; + } + + protected: + DeclaredPimpl() : ptr(Life::life.Create()) + {} + + private: + const Ptr ptr; + }; + + template class Del> + class InheritedPimpl : private Private::HaveAPimplLife > + { + typedef Private::HaveAPimplLife > Life; + + public: + const Ptr LOKI_INHERITED_PIMPL_NAME; + + protected: + InheritedPimpl() : LOKI_INHERITED_PIMPL_NAME(Life::life.Create()) + {} + }; + + ///////////////////// + // Rimpl usage policies + ///////////////////// + + template class DeletePolicy> + class DeclaredRimpl : public Impl + { + protected: + DeclaredRimpl() + {} + }; + + + template class Del> + class InheritedRimpl : private Private::HaveAPimplLife > + { + typedef Private::HaveAPimplLife > Life; + + public: + Impl& LOKI_INHERITED_RIMPL_NAME; + + protected: + InheritedRimpl() : + LOKI_INHERITED_RIMPL_NAME(*Life::life.Create()) + {} + + private: + InheritedRimpl& operator=(const InheritedRimpl&); + }; + + + + + ///////////////////// + // Wrapper for "pointer to implementation" alias pimpl. + // Impl: implementation class + // PointerTypePolicy: arbitrary pointer implementation + // DeletePolicy: delete implementation object on destruction of PtrImpl + // UsagePolicy: how to access the stored pointer, as pointer, checked, unchecked + ///////////////////// + + + template + < + class Impl, + class PointerPolicy = Impl*, + template class DeletePolicy = AutoDeletePimpl, + template class> class UsagePolicy = InheritedPimpl + > + class PtrImpl : public UsagePolicy + { + typedef PimplLife Life; + + public: + + typedef Impl ImplType; + typedef PointerPolicy PointerType; + + PtrImpl() : UsagePolicy()//Private::HaveALife::life.Create()) + {} + + PtrImpl(PointerPolicy pimpl) : UsagePolicy(pimpl) + {} + + virtual ~PtrImpl() + {} + }; + + + ///////////////////// + // Predefined convenience "templated typedef" + ///////////////////// + + + template + struct Pimpl + { + typedef PtrImpl + < + Impl, + Impl*, + AutoDeletePimpl, + DeclaredPimpl + > + Type; + + typedef PtrImpl + < + Impl, + Impl*, + AutoDeletePimpl, + InheritedPimpl + > + Owner; + }; + + + template + struct Rimpl + { + + typedef PtrImpl + < + Impl, + Impl*, + DontDeletePimpl, + DeclaredRimpl + > + Type; + + + typedef PimplLife + < + Type, + Type*, + AutoDeletePimpl + > + Life; + + + + typedef PtrImpl + < + Impl, + Impl*, + AutoDeletePimpl, + InheritedRimpl + > + Owner; + + }; + + +} + +#endif diff --git a/include/loki/PimplDef.h b/include/loki/PimplDef.h new file mode 100755 index 0000000..3f9d40b --- /dev/null +++ b/include/loki/PimplDef.h @@ -0,0 +1,70 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2006 Peter Kümmel +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author makes no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// +#ifndef LOKI_PIMPLDEF_H +#define LOKI_PIMPLDEF_H + +#include + +namespace Loki +{ + template + < + class Impl, + class Ptr, + template class Del + > + inline + PimplLife::PimplLife() //: ptr(Ptr()) this owerwrites the pointer to PtrImpl + {} // when using DeclaredRimpl!! + + template + < + class Impl, + class Ptr, + template class Del + > + inline + PimplLife::~PimplLife() + { + Del::Destroy( ptr ); + } + + template + < + class Impl, + class Ptr, + template class Del + > + template + inline + PimplLife::operator T&() + { + ptr = Ptr( new Impl ); + return *ptr; + } + + template + < + class Impl, + class Ptr, + template class Del + > + inline + Ptr + PimplLife::Create() + { + ptr = Ptr( new Impl ); + return ptr; + } +} + +#endif