int * ptr = new int;handle< int > h1( manager, ptr );handle< int > h2 = h1;handle< int > h3( manager, ptr );
This is the first part that dosn't translate quite directly to boost::shared_ptr. With shared_ptr, one should only create smart_ptrs from other smart_ptrs, except for the one instance where the pointer is being created. E.g. you'd do this:
shared_ptr< int > ptr ( new int );shared_ptr< int > h1( ptr );shared_ptr< int > h2 = h1;shared_ptr< int > h3( ptr );
This is because the shared_ptrs don't share a manager class that they are forced to mantain. This means that doing this:
int * ptr = new int;shared_ptr< int > h1( ptr );shared_ptr< int > h2( ptr );
Can cause ptr to end up getting deleted twice (since shared_ptrs were constructed from the same raw poniter twice). So, this can be a problem if you're working with a lot of legacy raw pointers code - otherwise, just never store the raw pointer and you're good to go :-).
The second bit has to do with using the "this" pointer - it's a raw pointer. This is probably best dealt with by mantaining a boost::weak_ptr to oneself. Here's the version I come up with on my first try:
class ArchiveFile { //self is not needed for this class, but is provided for consistancy: boost::weak_ptr< Archive > self; boost::shared_ptr< Archive > parent;public: Archive( boost::shared_ptr< ArchiveFile > & initial_handle , boost::shared_ptr< Archive > parent ) : parent( parent ) { initial_handle = boost::shared_ptr< Archive >( this ); self = initial_handle; }};class Archive { //this time we do need self, to pass to dependant ArchiveFile(s) boost::weak_ptr< Archive > self;public: Archive( boost::shared_ptr< Archive > & initial_handle ) { initial_handle = boost::shared_ptr< Archive >( this ); self = initial_handle; } boost::shared_ptr< ArchiveFile > createfile( ... ) { boost::shared_ptr< ArchiveFile > archive_file; new ArchiveFile( archive_file , boost::shared_ptr< Archive >( self ) ); return archive_file; }};class ArchiveManager { //creates/returns archives //no self, since we gotta end the line somewhere...public: boost::shared_ptr< Archive > createarchive( ... ) { boost::shared_ptr< Archive > archive; new Archive( archive ); return archive; }};
Someone else can probably come up with a much less hacky way to do this.
Edit: Fixes, and related notes:
"new ArchiveFile( archive_file , boost::shared_ptr< Archive >( self ) );" - shared_ptr explicit cast necessary to upgrade from a weak_ptr - this will throw if weak_ptr ever points to a deleted item, but that should never happen (if self is deleted, then "this" has been deleted, and that means we should never be in a function referencing this or self in the first place).
"initial_handle = boost::shared_ptr< Archive >( this );" - this assumes that Archive is indeed being dynamically allocated. Note that we never take the return of new in these examples :-/.
Reason for this ugly "initial_handle = ..." stuff in the first place instead of just doing boost::shared_ptr< Archive > archive( new Archive( archive ) ); - danger will robson, Archive will be constructed with a non-constructed boost::shared_ptr, which is just plain bad mojo - weak_ptr will likely end up pointing to 0xBAADF00D or similar.
Finally, instead of this ugly hack, I'd instead define my classes so I can just do:
shared_ptr< ArchiveManager > manager ( new ArchiveManager );
shared_ptr< Archive > archive ( new Archive( manager , "name" );
shared_ptr< ArchiveFile > file( new ArchiveFile( archive , "filename" ) );
instead of:
shared_ptr< ArchiveManager > manager ( new ArchiveManager );
shared_ptr< Archive > archive( manager->createArchive( "name" );
shared_ptr< ArchiveFile > file( archive->createFile( "filename" ) );
This also has the benifit of not needing to write accessory functions createArchive and createFile.
[Edited by - MaulingMonkey on May 29, 2005 2:18:27 PM]