yigal chripun Wrote:

> of the three above I think option 3 is the worst design and option 2 is my 
> favorite design. I think that in reality you'll almost always want to define 
> such an interface and I really can't think of any useful use cases for an 
> unrestricted template parameter as in C++. 

I think there are some.  In C++ using "<<" to extract a type T to an output 
stream is common.  Similarly, you could do something like dividing (x.size() + 
0.0)/x.capacity() to find the ratio of internal fragmentation, assuming most of 
the containers in question have a capacity method.  Another common example is 
creating a type like "Optional<T>" which wraps up a boolean plus a T to allow 
you to have "optional" values, e.g. the "this value is not set" concept.

template<class T> class Optional {
   T x;
   bool have;
public:
   Optional(bool have1 = false) : have(have1) {}
   Optional(T & x1) : x(x1), have(true){}
   bool haveValue() { return have; }
   T & get() { assert(have); return x; }
};

Which is useful for passing around lists of "configuration options" etc.

Essentially, any time you want to leverage a property common to a lot of 
different objects and with the same API across all of them, but don't want to 
(or can't) build that property into an inheritance diagram.  Often in C++ the 
reason you can't or don't add a virtual method (toString) to solve the same 
problem is either that (1) you don't have access to the base class code, or (2) 
it's a template and you can't have virtual templates.

As Bill Clinton said, "It depends on what the meaning of IS-A is."

Often a bunch of types have a kind of unrecognized "IS-A" relationship -- they 
all have some common characteristic that is not recognized as common (by the 
type system) until you come along to write code that deals with that 
characteristic.  (But if the T code is changing it's fragile to do this.)

Kevin

Reply via email to