$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Dan Rosen (dan.rosen_at_[hidden])
Date: 2005-03-25 21:21:01
> 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).
Okay, I figured out a way to make this work. It's terrible and I hate
it, and I think the simple approach (private ctor/dtor) is best, but I
feel like I have to post my solution for geeky completeness. Anyway,
here it is:
template <typename T> class noninstantiable {
protected:
virtual void myob () = 0;
};
template <typename T> void noninstantiable<T>::myob () { }
template <typename T> class instantiable : public T {
private:
virtual void myob () { this->noninstantiable<T>::myob(); }
};
If this isn't self-explanatory, what's going on here is that
noninstantiable<> is basically the same as before, but instantiable<>
forces its clients to derive from noninstantiable by referring to its
myob() member directly. So there are four scenarios:
class A { };
class B : public noninstantiable<B> { };
typedef instantiable<A> C;
typedef instantiable<B> D;
A a; // fine
B b; // error: myob not implemented
C c; // error: doesn't derive from noninstantiable
D d; // fine
This still doesn't allow clients to write literally zero code, but it
does close the loophole of case C above. Again, though, you'll have a
hard time convincing me that this is even marginally better than just
having a private ctor/dtor and explicitly declaring the friends who
you want to allow instantiation privileges to. This approach is less
safe, has more overhead, and is arcane.
dr