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
# 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:27:49 +00:00
2006-01-28 20:13:57 +00:00
//////////////////////////////////////////
// simple const propagating pointer
//////////////////////////////////////////
template < class T >
struct ConstPropPtr
{
2006-03-02 09:55:37 +00:00
explicit ConstPropPtr ( T * p ) : ptr_ ( p ) { }
~ ConstPropPtr ( ) { delete ptr_ ; ptr_ = 0 ; }
T * operator - > ( ) { return ptr_ ; }
T & operator * ( ) { return * ptr_ ; }
const T * operator - > ( ) const { return ptr_ ; }
const T & operator * ( ) const { return * ptr_ ; }
2006-01-28 20:13:57 +00:00
private :
ConstPropPtr ( ) ;
ConstPropPtr ( const ConstPropPtr & ) ;
ConstPropPtr & operator = ( const ConstPropPtr & ) ;
T * ptr_ ;
} ;
/////////////////////
// Pimpl
/////////////////////
template
<
class T ,
typename Pointer = ConstPropPtr < T >
>
class Pimpl
{
2006-01-16 13:27:49 +00:00
public :
2006-01-28 20:13:57 +00:00
typedef T Impl ;
2006-01-16 13:27:49 +00:00
2006-01-28 20:13:57 +00:00
Pimpl ( ) : ptr_ ( new T )
{ }
2006-01-23 17:23:46 +00:00
2006-03-02 09:55:37 +00:00
~ Pimpl ( )
{
// Don't compile with incomplete type
//
// If compilation brakes here make sure
// the compiler does not auto-generate the
// destructor of the class hosting the pimpl:
// - implement the destructor of the class
// - don't inline the destructor
typedef char T_must_be_defined [ sizeof ( T ) ? 1 : - 1 ] ;
}
2006-01-28 20:13:57 +00:00
T * operator - > ( )
2006-01-23 17:23:46 +00:00
{
2006-01-28 20:13:57 +00:00
return ptr_ . operator - > ( ) ;
2006-01-23 17:23:46 +00:00
}
2006-01-28 20:13:57 +00:00
T & operator * ( )
2006-01-23 17:23:46 +00:00
{
2006-01-28 20:13:57 +00:00
return ptr_ . operator * ( ) ;
2006-01-23 17:23:46 +00:00
}
2006-01-28 20:13:57 +00:00
const T * operator - > ( ) const
2006-01-15 22:03:10 +00:00
{
2006-01-28 20:13:57 +00:00
return ptr_ . operator - > ( ) ;
2006-01-15 22:03:10 +00:00
}
2006-01-28 20:13:57 +00:00
const T & operator * ( ) const
2006-01-15 22:03:10 +00:00
{
2006-01-28 20:13:57 +00:00
return ptr_ . operator * ( ) ;
2006-01-15 22:03:10 +00:00
}
2006-01-28 20:13:57 +00:00
Pointer & wrapped ( )
{
return ptr_ ;
}
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
const Pointer & wrapped ( ) const
{
return ptr_ ;
}
2006-01-15 22:03:10 +00:00
private :
2006-01-28 20:13:57 +00:00
Pimpl ( const Pimpl & ) ;
Pimpl & operator = ( const Pimpl & ) ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
Pointer ptr_ ;
2006-01-16 13:27:49 +00:00
} ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
template < class T , typename Pointer = ConstPropPtr < T > >
struct PimplOwner
{
Pimpl < T , Pointer > LOKI_INHERITED_PIMPL_NAME ;
} ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
//////////////////////////////////////////
// template for the implementations
//////////////////////////////////////////
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
template < class T >
struct ImplT ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
template < class T , template < class > class Ptr = ConstPropPtr >
struct PimplT
2006-01-15 22:03:10 +00:00
{
2006-01-28 20:13:57 +00:00
typedef T Impl ;
2006-01-16 13:30:26 +00:00
// declare pimpl
2006-01-28 20:13:57 +00:00
typedef Pimpl < ImplT < T > , Ptr < ImplT < T > > > Type ;
2006-01-15 22:03:10 +00:00
2006-01-16 13:30:26 +00:00
// inherit pimpl
2006-01-28 20:13:57 +00:00
typedef PimplOwner < ImplT < T > , Ptr < ImplT < T > > > Owner ;
} ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
template < class T , class UsedPimpl = typename PimplT < T > : : Type >
struct RimplT
2006-01-15 22:03:10 +00:00
{
2006-01-28 20:13:57 +00:00
typedef typename UsedPimpl : : Impl & Type ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
class Owner
{
UsedPimpl pimpl ;
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
public :
Owner ( ) : LOKI_INHERITED_RIMPL_NAME ( * pimpl )
{ }
2006-01-15 22:03:10 +00:00
2006-01-28 20:13:57 +00:00
Type LOKI_INHERITED_RIMPL_NAME ;
} ;
} ;
2006-01-15 22:03:10 +00:00
}
# endif
2006-01-16 19:05:09 +00:00
// $Log$
2006-03-02 09:55:37 +00:00
// Revision 1.17 2006/03/02 09:55:37 syntheticpp
// don't compile with incomplete types
//
2006-03-01 15:20:19 +00:00
// Revision 1.16 2006/03/01 15:20:19 syntheticpp
// add documenation how to avoid the -deletion of pointer to incomplete type- error
//
2006-01-28 20:13:57 +00:00
// Revision 1.15 2006/01/28 20:12:56 syntheticpp
// replace implementation with a auto-create and propagating-const wrapper for smart pointers which auto delete the holded pointer on destruction
//
2006-01-26 14:28:59 +00:00
// Revision 1.14 2006/01/26 14:28:59 syntheticpp
// remove wrong 'typename'
//
2006-01-23 17:23:46 +00:00
// Revision 1.13 2006/01/23 17:22:49 syntheticpp
// add support of deep constness, only supported by (future) Loki::SmartPtr, not supported by boost::shared_ptr and plain pointer. Maybe deep constness forces a redesign of Pimpl. Is there a way to support deep constness by a rimpl?
//
2006-01-19 18:16:39 +00:00
// Revision 1.12 2006/01/19 18:16:39 syntheticpp
// disable usage with auto_ptr: don't compile with std::auto_ptr
//
2006-01-18 19:03:25 +00:00
// Revision 1.11 2006/01/18 19:03:06 syntheticpp
// make rimpl type really a reference
//
2006-01-18 16:49:32 +00:00
// Revision 1.10 2006/01/18 16:49:06 syntheticpp
// move definition of the destructor to extra file, because msvc tries to use the incomplete type; not inlining does not help; maybe this is a compiler bug.
//
2006-01-17 12:03:36 +00:00
// Revision 1.9 2006/01/17 12:03:36 syntheticpp
// add comment about auto_ptr
//
2006-01-17 11:07:34 +00:00
// Revision 1.8 2006/01/17 11:07:34 syntheticpp
// AutoPtrHolderChecked inherits from AutoPtrHolder
//
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.
//