
But this is not what I was suggesting. [snip] This makes it so that client code can indeed do absolutely nothing, and still be guaranteed that rogue instances cannot be created.
Ah, interesting pattern. Thanks for the clarification. I think there are two separable design concerns here. One is the singleton behavior, and the other is the non-instantiable behavior. Singleton conceptually has a dependency on non-instantiable, but there isn't a reverse dependency there. So I'd separate the two something like this: class noninstantiable { protected: virtual void myob () = 0; }; template <typename T> class instantiable : public T { private: virtual void myob () { } }; That's the first half -- it's saying something like "a class deriving from noninstantiable is not instantiable except in certain contexts where you explicitly declare it to be instantiable." [Clients are also prevented from calling myob().] This doesn't prevent clients from intentionally saying "I want to instantiate foo here" by using instantiable<foo> explicitly, but it does prevent unintentional instantiation, which is probably good enough. The second half is the singleton part. You'd do something like: template <typename T> class singleton : public instantiable<T> { // ... }; All that said, there's still a flaw in your approach, which I've inherited in mine. That is: neither of our singleton<> class templates actually force clients to derive from their intended bases (singleton_base in your case, and noninstantiable in mine). In other words, your assertion that "client code can indeed do absolutely nothing" isn't precisely true: clients still have to derive from a special base to be safe, and there's no guarantee that will be done. Addressing your original question regarding whether enabling the virtual function safety mechanism in debug mode, that seems reasonable. Assuming there's nothing wrong with the way I've refactored things here, you can contain that safety mechanism within the noninstantiable/instantiable hierarchy without polluting the singleton's interface. (Just wrap the declarations for "myob" in an #ifdef DEBUG block and you're done.) But I'd still like to know your motivation for not just doing what strikes me as the obvious and idiomatic thing: making clients define private ctor/dtor. It's trivial to do, everybody knows what it means, and you get the same safety without any virtual function overhead. Is there some reason you're trying so hard to avoid this? Cheers, dr