Boost logo

Boost :

From: Jason Hise (chaos_at_[hidden])
Date: 2005-03-24 10:27:13


Early on, I had the idea to disable creation of a user's singleton by
making the base class have one pure virtual function. The user's
derived singleton would become an abstract class, and thus not be able
to be instantiated. Then the user would refer to the singleton via an
even further derived class, like follows:

class singleton_base
{
private:
    virtual void define_to_enable_creation ( ) = 0;
};

template < typename Type >
class singleton : public Type
{
private:
    virtual void define_to_enable_creation ( ) { }

protected:
    // constructors and such were here

public:
    // interface was here
};

//-------------------------------------------------

class test_singleton : public singleton_base
{
public:
    void do_something ( );
};

int main ( )
{
    test_singleton t; // this line would not compile
    singleton < test_singleton > t2; // neither would this
    singleton < test_singleton >::pointer ptr; // this would be the only
access mechanism
    ptr->do_something ( );

    return 0;
}

This idea concerned some originally because remembering to use singleton
< test_singleton > instead of just test_singleton everywhere in client
code could get ugly, and define_to_enable_creation was the only virtual
function in the class, introducing what might be unacceptable overhead.
As a result, I removed it and changed the design to a more conventional
CRTP implementation. I resigned myself to the fact that the user would
just need to remember to make the default ctor and dtor protected.

In the current incarnation of the library, the client singleton's
constructors are protected, and to gain access to them the creator
policies define their own private class internally which derives from
the singleton type and makes the ctors and dtor public. This is similar
to the pattern above, except that client code doesn't have to worry or
know about that most derived rung on the class hierarchy.

If I were to re-enable the virtual function check to make the client
singleton abstract, the overhead of using virtual functions would again
come back. However, having it in place would prevent unsafe
instantiations regardless of the access level client code uses for
singleton constructors. So would there be any objections to reinstating
this mechanism just in debug mode? This way unsafe instantiations could
be caught, and in release mode you wouldn't have to pay for the catching
mechanism at all. Thoughts?

-Jason


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk