Boost logo

Boost :

From: Dan Rosen (dan.rosen_at_[hidden])
Date: 2005-03-24 11:47:58


Hi Jason,

I haven't looked at singleton in any detail, so I can't answer your
real question, but I wanted to offer a small suggestion, for what it's
worth:

Rather than having a special function spelled
"define_to_enable_creation," I wonder if it would be reasonable to
declare singleton_base's destructor as pure virtual, forcing client
code such as test_singleton to implement a destructor. If you wanted
to enable the virtual behavior only for extra checking in debug mode,
that'd be fine too:

  class singleton_base {
  protected:
  #ifdef DEBUG
    virtual ~singleton_base() = 0;
  #endif
  // ...
  };

  class test_singleton : public singleton_base {
  protected:
    ~test_singleton() { }
    // ...
  };

In debug mode, test_singleton's destructor is virtual as defined by
its base class, and is necessary to implement. In release mode,
test_singleton's destructor is not virtual unless you specify it to
be. And implementing a trivial destructor like this is never harmful
anyway.

Just a thought, but I might be totally missing something :) Cheers,
dr

On Thu, 24 Mar 2005 10:27:13 -0500, Jason Hise <chaos_at_[hidden]> wrote:
> 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
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>


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