What's wrong with D's templates?

Kevin Bealer kevinbealer at gmail.com
Mon Dec 21 13:15:12 PST 2009


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




More information about the Digitalmars-d mailing list