
From: Jason Hise <chaos@ezequal.com>
Rob Stewart wrote:
with:
class make_me_a_singleton : public singleton_base { ... };
without:
class make_me_a_singleton { ... private: make_me_a_singleton() { }; ~make_me_a_singleton() { }; };
The first version is achievable just as easily with noninstantiable as with singleton_base. If singleton_base offers nothing more than noninstantiable, then the choice of names is debatable.
If you check the current version of the library, you will notice that 'singleton_base' offers a lot more than non-instantiable, specifically in the realm of control over the instance lifetime, dependency management between multiple singletons, and safety with regard to using singletons that have already been destroyed.
Then that clearly argues for putting the functionality in singleton_base and not a separate noninstantiable class (though that would be useful on its own).
To make the class instantiable by the framework, the supplied Creator policy class must have access to the ctor. You can make the ctor private and then make the Creator a friend, but then outside code can call creator<T>::create() to create an instance. If creator<T>::create() is private, and singleton<T> is a friend, then only singleton<T> can instantiate a T. That, of course, is a lot of machinery just to ensure that T can only ever be instantiated as a Singleton.
I agree, this might be a bit much machinery, especially because creator policies are likely to be written often by client code. However, there is a way to move all of the machinery into the library, so that client written creators don't have to re-implement it. Create and destroy are not static functions, as a creator must be allowed to have a saved state. These are just plain old member functions, and require a creator instance in order to be called. Thus, by adding a creator base with a pure virtual function, we can make all creators uninstantiable and unusable by client code. This creator base could then additionally provide the derived instantiable singleton class needed by most creators, making it even easier for client code to write their own creators.
IOW, if basic_singleton requires that the Creator template argument derive from creator_base, and creator_base uses a noninstantiable technique, then the client cannot create a Creator instance, so the only way to create an instance of type T is if T permits it. Provided that using basic_singleton<T> places no contrary burdens on T such that basic_singleton<T> controls (a) common, Singleton instance(s), yet other T's can be instantiated directly, it sounds good. Unfortunately, the functionality you described was provided by singleton_base suggests that this isn't the case. Am I missing something still? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;