What's wrong with D's templates?

yigal chripun yigal100 at gmail.com
Mon Dec 21 06:26:08 PST 2009


Don Wrote:

> yigal chripun wrote:
> > Don Wrote:
> >>> The way I see it we have three options:
> >>>
> >>> assume we have these definitions:
> >>> interface I {...}
> >>> class Foo : I {...}
> >>> class Bar {...} // structurally compatible to I
> >>>
> >>> template tp (I) {...}
> >>>
> >>> 1) .Net nominative typing:
> >>> tp!(Foo) // OK
> >>> tp!(Bar) //not OK
> >>>
> >>> 2) structural typing (similllar to Go?)
> >>> tp!(Foo) // OK
> >>> tp!(Bar) // also OK
> >>>
> >>> 3) C++ style templates where the compatibility check is against the *body* of the template.
> >>>
> >>> 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++. 
> >> You forgot option 4:
> >>
> >> 4) D2 constrained templates, where the condition is checked inside the 
> >> template constraint.
> >>
> >> This is more powerful than option 2, because:
> >>
> >> (1) there are cases where you want MORE constraints than simply an 
> >> interface; and (2) only a subset of constraints can be expressed as an 
> >> interface.
> >> Also a minor point: (3) interfaces don't work for built-in types.
> >>
> >> Better still would be to make it impossible to compile a template which 
> >> made use of a feature not provided through a constraint.
> >>
> > 
> > I wouldn't give that a sepoarate option number, IMO this is a variation on option2. regarding your notes:
> > when you can express the same concept in both ways, using an interface is esier to read & understand IMO. What about having a combination of the two designs? you define an interface and allow optionally defining additional constraints _on_the_interface_ instead of the template.
> > I think this complies with your points (1) and (2) and is better since you don't need to repeat the constraints at the call site (each template that uses that type needs to repeat the constraint).
> 
> I don't think interfaces are flexible enough for that.
> EG, how do you express that the type I must have a template function 
> void baz!(X)(X x) ?
> There's more to a type, than just a list of the virtual functions which 
> it supports.

I agree that interfaces don't support this ATM. That's why i suggested to add constraints to them. 
e.g.
Interface I if isFoo!(I) {...}  // one possible syntax
other approaches could be :
1) add non-virtual functions to interfaces (Andrei once suggested this)
2) add more meta-data with annotations
etc.. 

> 
> > even if you factor out the checks into a separate "isFoo" template you still need to add to each template declaration "if isFoo!(T)" which really should be done by the compiler instead.
> > 
> > regarding point(3) - this is orthogonal IMO. Ideally I'd like to see this distinction between builtin type and user defined one removed. int should be treated in the same manner as a user defined struct. 
> > 
> > I completely agree about not compiling templates that use features not defined by constraints. This is in fact the main point I was trying to make in this thread. 
> 
> The problem is, I'm not sure that it's feasible in general. At least, 
> it's not obvious how to do it.
> 



More information about the Digitalmars-d mailing list