2006-01-15 22:03:10 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// 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 <loki/TypeTraits.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef LOKI_INHERITED_PIMPL_NAME
|
2006-01-16 13:27:49 +00:00
|
|
|
|
#define LOKI_INHERITED_PIMPL_NAME d
|
2006-01-15 22:03:10 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef LOKI_INHERITED_RIMPL_NAME
|
2006-01-16 13:27:49 +00:00
|
|
|
|
#define LOKI_INHERITED_RIMPL_NAME d
|
2006-01-15 22:03:10 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace Loki
|
|
|
|
|
{
|
2006-01-16 13:30:26 +00:00
|
|
|
|
/////////////////////
|
2006-01-16 13:27:49 +00:00
|
|
|
|
// template for the implementations
|
|
|
|
|
/////////////////////
|
2006-01-15 22:03:10 +00:00
|
|
|
|
template<class T>
|
|
|
|
|
struct Impl;
|
|
|
|
|
|
|
|
|
|
|
2006-01-16 19:48:23 +00:00
|
|
|
|
|
|
|
|
|
|
2006-01-15 22:03:10 +00:00
|
|
|
|
/////////////////////
|
|
|
|
|
// creation policies
|
|
|
|
|
/////////////////////
|
2006-01-16 13:27:49 +00:00
|
|
|
|
// hard coded creation preferred
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// destroy policies
|
|
|
|
|
/////////////////////
|
|
|
|
|
template<class T>
|
|
|
|
|
struct AutoDeletePimpl
|
|
|
|
|
{
|
2006-01-16 13:27:49 +00:00
|
|
|
|
static void Destroy(T ptr)
|
2006-01-16 13:30:26 +00:00
|
|
|
|
{
|
|
|
|
|
typedef char T_must_be_defined[
|
|
|
|
|
sizeof(typename TypeTraits<T>::PointeeType) ? 1 : -1 ];
|
|
|
|
|
delete ptr;
|
|
|
|
|
ptr = 0;
|
|
|
|
|
}
|
2006-01-15 22:03:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct DontDeletePimpl
|
|
|
|
|
{
|
|
|
|
|
static void Destroy(T)
|
|
|
|
|
{}
|
|
|
|
|
};
|
|
|
|
|
|
2006-01-16 19:48:23 +00:00
|
|
|
|
/////////////////////
|
|
|
|
|
// error handling
|
|
|
|
|
/////////////////////
|
|
|
|
|
template<class T>
|
|
|
|
|
struct ExceptionOnPimplError
|
|
|
|
|
{
|
|
|
|
|
struct Exception : public std::exception
|
|
|
|
|
{
|
|
|
|
|
const char* what() const throw() { return "error in loki/Pimpl.h"; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void PimplError()
|
|
|
|
|
{
|
|
|
|
|
throw Exception();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct IgnorPimplError
|
|
|
|
|
{
|
|
|
|
|
static void PimplError()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
};
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
/////////////////////
|
2006-01-16 13:27:49 +00:00
|
|
|
|
// Helper class AutoPtrHolder to manage pimpl lifetime
|
2006-01-15 22:03:10 +00:00
|
|
|
|
/////////////////////
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
namespace Private
|
|
|
|
|
{
|
|
|
|
|
template
|
|
|
|
|
<
|
|
|
|
|
class Impl,
|
|
|
|
|
class Ptr,
|
|
|
|
|
template<class> class Del
|
|
|
|
|
>
|
|
|
|
|
struct AutoPtrHolder
|
|
|
|
|
{
|
2006-01-16 18:21:01 +00:00
|
|
|
|
AutoPtrHolder() : ptr(Ptr())
|
|
|
|
|
{}
|
2006-01-16 13:30:26 +00:00
|
|
|
|
|
|
|
|
|
~AutoPtrHolder()
|
|
|
|
|
{
|
|
|
|
|
// delete automatically by the delete policy
|
|
|
|
|
Del<Ptr>::Destroy( ptr );
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-16 18:21:01 +00:00
|
|
|
|
Ptr Create()
|
|
|
|
|
{
|
|
|
|
|
ptr = Ptr( new Impl );
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ptr ptr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template
|
|
|
|
|
<
|
|
|
|
|
class Impl,
|
|
|
|
|
class Ptr,
|
2006-01-16 19:48:23 +00:00
|
|
|
|
template<class> class Del,
|
|
|
|
|
template<class> class ErrorPolicy = ExceptionOnPimplError
|
2006-01-16 18:21:01 +00:00
|
|
|
|
>
|
2006-01-16 19:48:23 +00:00
|
|
|
|
struct AutoPtrHolderChecked
|
2006-01-16 18:21:01 +00:00
|
|
|
|
{
|
|
|
|
|
static bool init_;
|
|
|
|
|
|
|
|
|
|
AutoPtrHolderChecked() : ptr(Ptr())
|
|
|
|
|
{
|
|
|
|
|
init_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~AutoPtrHolderChecked()
|
|
|
|
|
{
|
|
|
|
|
// delete automatically by the delete policy
|
|
|
|
|
Del<Ptr>::Destroy( ptr );
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
template<class T>
|
|
|
|
|
operator T&()
|
|
|
|
|
{
|
2006-01-16 19:48:23 +00:00
|
|
|
|
// if this throws change the declaration order
|
|
|
|
|
// of the DeclaredRimpl construct
|
2006-01-16 18:21:01 +00:00
|
|
|
|
if(!init_)
|
2006-01-16 19:48:23 +00:00
|
|
|
|
ErrorPolicy<T>::PimplError();
|
2006-01-16 13:30:26 +00:00
|
|
|
|
Create();
|
|
|
|
|
return *ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ptr Create()
|
|
|
|
|
{
|
|
|
|
|
ptr = Ptr( new Impl );
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ptr ptr;
|
|
|
|
|
};
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
2006-01-16 18:21:01 +00:00
|
|
|
|
template
|
|
|
|
|
<
|
|
|
|
|
class Impl,
|
|
|
|
|
class Ptr,
|
2006-01-16 19:48:23 +00:00
|
|
|
|
template<class> class Del,
|
|
|
|
|
template<class> class Err
|
2006-01-16 18:21:01 +00:00
|
|
|
|
>
|
2006-01-16 19:48:23 +00:00
|
|
|
|
bool AutoPtrHolderChecked<Impl,Ptr,Del,Err>::init_ = false;
|
2006-01-16 18:21:01 +00:00
|
|
|
|
|
|
|
|
|
|
2006-01-15 22:03:10 +00:00
|
|
|
|
template<class T>
|
2006-01-16 13:27:49 +00:00
|
|
|
|
struct HavePtrHolder
|
2006-01-15 22:03:10 +00:00
|
|
|
|
{
|
2006-01-16 13:27:49 +00:00
|
|
|
|
T ptr;
|
2006-01-15 22:03:10 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// Pimpl usage policies
|
|
|
|
|
/////////////////////
|
|
|
|
|
|
|
|
|
|
template<class Impl, typename Ptr, template<class> class Del>
|
2006-01-16 13:27:49 +00:00
|
|
|
|
class InheritedPimpl : private
|
2006-01-16 13:30:26 +00:00
|
|
|
|
Private::HavePtrHolder<Private::AutoPtrHolder<Impl,Ptr,Del> >
|
2006-01-16 13:27:49 +00:00
|
|
|
|
{
|
|
|
|
|
typedef Private::HavePtrHolder<Private::AutoPtrHolder<Impl,Ptr,Del> > PtrHolder;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
const Ptr LOKI_INHERITED_PIMPL_NAME;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
InheritedPimpl() : LOKI_INHERITED_PIMPL_NAME(PtrHolder::ptr.Create())
|
|
|
|
|
{}
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
private:
|
|
|
|
|
InheritedPimpl& operator=(const InheritedPimpl&);
|
2006-01-16 13:27:49 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class Impl, typename Ptr, template<class> class Del>
|
2006-01-16 13:30:26 +00:00
|
|
|
|
class DeclaredPimpl : private
|
|
|
|
|
Private::HavePtrHolder<Private::AutoPtrHolder<Impl,Ptr,Del> >
|
2006-01-15 22:03:10 +00:00
|
|
|
|
{
|
2006-01-16 13:27:49 +00:00
|
|
|
|
typedef Private::HavePtrHolder<Private::AutoPtrHolder<Impl,Ptr,Del> > PtrHolder;
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Ptr operator->() const
|
|
|
|
|
{
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Impl& operator*() const
|
|
|
|
|
{
|
|
|
|
|
return *ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
2006-01-16 13:30:26 +00:00
|
|
|
|
DeclaredPimpl() : ptr(PtrHolder::ptr.Create())
|
2006-01-15 22:03:10 +00:00
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
private:
|
2006-01-16 13:30:26 +00:00
|
|
|
|
DeclaredPimpl& operator=(const DeclaredPimpl&);
|
2006-01-15 22:03:10 +00:00
|
|
|
|
const Ptr ptr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// Rimpl usage policies
|
|
|
|
|
/////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class Impl, typename Ptr, template<class> class Del>
|
2006-01-16 13:27:49 +00:00
|
|
|
|
class InheritedRimpl : private
|
2006-01-16 13:30:26 +00:00
|
|
|
|
Private::HavePtrHolder<Private::AutoPtrHolder<Impl,Ptr,Del> >
|
2006-01-15 22:03:10 +00:00
|
|
|
|
{
|
2006-01-16 13:27:49 +00:00
|
|
|
|
typedef Private::HavePtrHolder<Private::AutoPtrHolder<Impl,Ptr,Del> > PtrHolder;
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Impl& LOKI_INHERITED_RIMPL_NAME;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
InheritedRimpl() :
|
2006-01-16 13:27:49 +00:00
|
|
|
|
LOKI_INHERITED_RIMPL_NAME(*PtrHolder::ptr.Create())
|
2006-01-15 22:03:10 +00:00
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
InheritedRimpl& operator=(const InheritedRimpl&);
|
|
|
|
|
};
|
|
|
|
|
|
2006-01-16 13:27:49 +00:00
|
|
|
|
template<class Impl, typename PointerPolicy, template<class> class DeletePolicy>
|
|
|
|
|
class DeclaredRimpl : public Impl
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
DeclaredRimpl()
|
|
|
|
|
{}
|
|
|
|
|
};
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// 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> class DeletePolicy = AutoDeletePimpl,
|
|
|
|
|
template<class,class,template<class> class> class UsagePolicy = InheritedPimpl
|
|
|
|
|
>
|
|
|
|
|
class PtrImpl : public UsagePolicy<Impl,PointerPolicy,DeletePolicy>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
typedef Impl ImplType;
|
|
|
|
|
typedef PointerPolicy PointerType;
|
|
|
|
|
|
2006-01-16 13:27:49 +00:00
|
|
|
|
PtrImpl() : UsagePolicy<Impl,PointerPolicy,DeletePolicy>()
|
2006-01-15 22:03:10 +00:00
|
|
|
|
{}
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
private:
|
|
|
|
|
PtrImpl& operator=(const PtrImpl&);
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// Predefined convenience "templated typedef"
|
|
|
|
|
/////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct Pimpl
|
|
|
|
|
{
|
2006-01-16 13:30:26 +00:00
|
|
|
|
// declare pimpl
|
2006-01-15 22:03:10 +00:00
|
|
|
|
typedef PtrImpl
|
|
|
|
|
<
|
|
|
|
|
Impl<T>,
|
|
|
|
|
Impl<T>*,
|
|
|
|
|
AutoDeletePimpl,
|
|
|
|
|
DeclaredPimpl
|
|
|
|
|
>
|
|
|
|
|
Type;
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
// inherit pimpl
|
2006-01-15 22:03:10 +00:00
|
|
|
|
typedef PtrImpl
|
|
|
|
|
<
|
|
|
|
|
Impl<T>,
|
|
|
|
|
Impl<T>*,
|
|
|
|
|
AutoDeletePimpl,
|
|
|
|
|
InheritedPimpl
|
|
|
|
|
>
|
|
|
|
|
Owner;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
struct Rimpl
|
|
|
|
|
{
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
// declare rimpl
|
2006-01-15 22:03:10 +00:00
|
|
|
|
typedef PtrImpl
|
|
|
|
|
<
|
|
|
|
|
Impl<T>,
|
|
|
|
|
Impl<T>*,
|
|
|
|
|
DontDeletePimpl,
|
|
|
|
|
DeclaredRimpl
|
|
|
|
|
>
|
|
|
|
|
Type;
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
// init declared rimpl
|
2006-01-16 18:21:01 +00:00
|
|
|
|
typedef Private::AutoPtrHolderChecked
|
2006-01-15 22:03:10 +00:00
|
|
|
|
<
|
|
|
|
|
Type,
|
|
|
|
|
Type*,
|
|
|
|
|
AutoDeletePimpl
|
|
|
|
|
>
|
2006-01-16 13:27:49 +00:00
|
|
|
|
Init;
|
2006-01-15 22:03:10 +00:00
|
|
|
|
|
|
|
|
|
|
2006-01-16 13:30:26 +00:00
|
|
|
|
// ingerit rimpl
|
2006-01-15 22:03:10 +00:00
|
|
|
|
typedef PtrImpl
|
|
|
|
|
<
|
|
|
|
|
Impl<T>,
|
|
|
|
|
Impl<T>*,
|
|
|
|
|
AutoDeletePimpl,
|
|
|
|
|
InheritedRimpl
|
|
|
|
|
>
|
|
|
|
|
Owner;
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
2006-01-16 19:05:09 +00:00
|
|
|
|
|
|
|
|
|
// $Log$
|
2006-01-16 19:48:23 +00:00
|
|
|
|
// Revision 1.7 2006/01/16 19:48:23 syntheticpp
|
|
|
|
|
// add error policy
|
|
|
|
|
//
|
2006-01-16 19:05:09 +00:00
|
|
|
|
// Revision 1.6 2006/01/16 19:05:09 rich_sposato
|
|
|
|
|
// Added cvs keywords.
|
|
|
|
|
//
|