|
Boost : |
From: Miki Jovanovic (miki_at_[hidden])
Date: 2000-02-07 18:26:44
Hello all,
OK, first I have to appologise for my code being in my own style...
I have been working quite happily at work when an idea occured to
me on how to make the shared_ptr polymorphic. For whatever reason
I could not use the boost library, so I quickly jogged down this
version of a polymorphic smart pointer.
The problem I was trying to solve is: allow shared_ptr<DescendentClass>
to be used anywhere shared_ptr<ParentClass> is expected.
Below is the VERY VERY rough cut of the code. Basically I am just
bouncing the idea of you guys, to see if my approach has some merit.
The reason I rushed so, is that I cannot find anything wrong with it,
and frankly I cannot believe my idea is that good. Method has potential
to be backwardly compatible with shared_ptr, it is just as fast, and
provides all the functionality one needs from a polymorphic pointer.
So, before I invest days of my life making this into presentable form,
can you guys comment on the concept.
Cheers,
Miki Jovanovic.
// main.cpp
#ifndef NULL
#define NULL 0
#endif
/*
* NonCopyable
*/
class NonCopyable {
protected:
NonCopyable() {} // so noone can create objects of this type
~NonCopyable() {} // so people don't delete objects by calling
this non-virtual destructor
private:
NonCopyable( const NonCopyable& ); // disable copy constructor
operator=( const NonCopyable& ); // disable copy operator
};
/*
* PtrBase
*/
template <typename T> class PtrBase : NonCopyable {
public: // public interface
template<typename D> PtrBase& cast( const PtrBase<D>& ptr ) {
if ( _pRefCount != ptr._pRefCount ) {
release();
dynamicShare( ptr._pObject, ptr._pRefCount );
}
return *this;
}
void clear() {
release();
assign( NULL );
}
protected: // helper routines
PtrBase() {}
explicit PtrBase( T* pObject ) { assign( pObject ); }
~PtrBase() {
release();
}
void assign( T* pObject ) {
try {
_pRefCount = new int(1);
}
catch ( ... ) {
delete pObject;
throw;
}
_pObject = pObject;
}
template<typename D> void share( D* pObject, int* pRefCount ) {
_pObject = pObject;
_pRefCount = pRefCount;
(*_pRefCount)++;
}
template<typename D> void dynamicShare( D* pObject, int*
pRefCount ) {
T *pCastObject = dynamic_cast<T*>( pObject );
if ( pObject == NULL || pCastObject != NULL ) {
_pObject = pCastObject;
_pRefCount = _pRefCount;
(*_pRefCount)++;
}
else {
assign( NULL ); // dynamic_cast failed
}
}
void release() {
if ( _pRefCount != NULL && --(*_pRefCount) <= 0 ) {
delete _pRefCount;
delete _pObject;
}
}
protected: // data
T *_pObject;
int *_pRefCount;
};
/*
* Ptr
*/
template<typename T, class B = PtrBase<T> > class Ptr : public B {
public:
explicit Ptr( T* pObject = NULL ) : B( pObject ) {}
Ptr( const Ptr& ptr ) { share( ptr._pObject, ptr._pRefCount ); }
Ptr& operator=( const Ptr& ptr ) {
if ( _pRefCount != ptr._pRefCount ) {
release();
share( ptr._pObject, ptr._pRefCount );
}
return *this;
}
T* ptr() const { return static_cast<T*>( _pObject ); }
T* operator->() const { return ptr(); }
};
class X {
public:
virtual ~X() {}
virtual void method() {}
void x() {}
};
class Y : public X {
public:
virtual ~Y() {}
virtual void method() {}
void y() {}
};
class Z : public Y {
public:
virtual ~Z() {}
virtual void method() {}
void z() {}
};
typedef Ptr<X> XPtr;
typedef Ptr<Y,XPtr> YPtr;
typedef Ptr<Z,YPtr> ZPtr;
/*
* t
*/
void t( const XPtr& p ) {
p->method();
}
/*
* main
*/
int main( int, char** ) {
XPtr x1( new X() );
YPtr y1( new Y() );
ZPtr z1( new Z() );
XPtr x2( z1 );
y1 = z1;
z1.cast( x2 );
X *pX = z1.ptr();
Y *pY = z1.ptr();
Z *pZ = z1.ptr();
z1->z();
y1->y();
t( x1 );
t( z1 );
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk