Boost logo

Boost :

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


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