Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2002-10-08 07:55:02


From: "Stephan Born" <yg-boost-users_at_[hidden]>
> Hello!
>
> I do some experiments on shared_ptr and weak_ptr. So I tried to use them
> for a singleton-class, which does not need an explicit
> singleton::release_instance method. The singleton-instance will be
> destroyed everytime the last external shared_ptr holding the instance
> goes out of scope. Is this a valid usage for weak_ptr? Are there any
> traps I do not see using these smart_ptrs in this context?
>
> The drawback of using shared_ptr with singleton is the need for a public
> destructor. But this is dangerous....it is possible to write
>
> singleton::singleton_ptr first_ptr = singleton::instance();
> delete first_ptr.get();
>
> Declaring the destructor as private is only possible when defining
> boost::checked_delete as friend of the singleton-class.
> ( there is a thread on comp.lang.c++.moderated with the topic
> 'specialization of function template as friend with MSVC6SP5 not
> possible' which deals with this problem of friendship... )
> 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.
>
> Is there a way to allow destruction of the instance only to shared_ptr?

Your class isn't a "canonical" singleton since those have one instance per
program; yours has one instance at a time. That aside, there are two ways to
prohibit deletion:

1. Make the destructor protected and return an instance of a derived class:

X.hpp:

class X
{
protected:

    ~X();

public:

    shared_ptr<X> instance();
};

X.cpp:

class X_impl: public X // not visible to clients
{
};

shared_ptr<X> X::instance()
{
    return shared_ptr<X>(new X_impl);
}

2. Use a custom private deallocator:

class X
{
private:

    ~X();
    static void destroy(X * p) { delete p; }

public:

    shared_ptr<X> instance()
    {
        return shared_ptr<X>(new X, X::destroy);
    }
};


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net