Nicola Musatti wrote:
Within the singleton class I hold the instance with a shared_ptr. I consider this the best option, as it guarantees the correct order of destruction when a singleton depends on another one.
But I *want* it to be delete automagically...and I do not see the danger: if there is a dependent second_singleton it would hold a shared_ptr to my singleton, and singleton would not be destroyed before second_singleton is destroyed by its own. Maybe it should be made an option by using policies....but I really do not the danger.
You should rely on the constructor that takes an additional deleter argument, something like (not compiled and almost certainly incomplete and incorrect):
class SingletonDeleter { friend class shared_ptr<Singleton>; operator() (Singleton *p) { delete p; } };
class Singleton { friend class SingletonDeleter; public: shared_ptr<Singleton,SingletonDeleter> instance() { if ( inst == 0 ) inst = shared_ptr<Singleton,SingletonDeleter> ( new Singleton,SingletonDeleter()); return inst; } };
typedef shared_ptr<Singleton,SingletonDeleter> SingletonPtr;
Yes, I fear it *is* incorrect ;) look at the bottom of the posting for my implelentation
Declaring the destructor as private is only possible when defining boost::checked_delete as friend of the singleton-class.
[...]
But then it is still possible to write the following code
singleton::singleton_ptr first_ptr = singleton::instance(); boost:checked_delete( first_ptr.get() );
OK, it's very unlikely to do it by chance, but it is possible.
Moreover, you rely on what should be an implementation detail.
OK, I hope that this will be the correct way: * I do not rely on implementation-detail ( make boost::checked_delete a friend ) * I provide my own deleter-functor <code> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/utility.hpp> class singleton : boost::noncopyable { public: typedef boost::shared_ptr< singleton > singleton_ptr; static singleton_ptr instance() { singleton_ptr tmp; if( s_instance.expired() ) { tmp.reset( new singleton, checked_deleter() ); // <-- NEW!!! s_instance = tmp; } else { tmp = boost::make_shared( s_instance ); } return tmp; } void foo() { // do something i++; } private: // NEW !!!! struct checked_deleter { operator() ( singleton * p_ ) { // does the same as boost::checked_delete from BOOST 1.28.0 typedef char type_must_be_complete[ sizeof( p_ ) ]; delete p_; } }; friend struct checked_deleter; typedef boost::weak_ptr< singleton > internal_singleton_ptr; singleton(){}; ~singleton(){}; // NOW IT'S PRIVATE !!! int i; static internal_singleton_ptr s_instance; }; singleton::internal_singleton_ptr singleton::s_instance; int main() { { singleton::singleton_ptr first_ptr = singleton::instance(); { singleton::singleton_ptr second_ptr = singleton::instance(); second_ptr->foo(); } first_ptr->foo(); } singleton::singleton_ptr another_ptr = singleton::instance(); // OK, these things do not work anymore..... //delete( another_ptr.get() ); //boost::checked_delete( another_ptr.get() ); //singleton::singleton_deleter deleter(); //deleter( another_ptr.get() ); another_ptr->foo(); return 0; } </code> -- --------------------------------------------------------------- Dipl.-Inf. (FH) Stephan Born | beusen Solutions GmbH fon: +49 30 549932-0 | Landsberger Allee 366 fax: +49 30 549932-21 | 12681 Berlin mailto:stephan.born@beusen.de | Germany --------------------------------------------------------------- PGP-Key verfügbar | PGP-Key available ---------------------------------------------------------------