Template issues in D

Bill Baxter dnewsgroup at billbaxter.com
Tue Feb 19 18:13:42 PST 2008


D has some compile-time programming features make other languages weep 
with jealousy.  However, the core features, those that have worked in 
C++ for years, are still buggy and incomplete.

These buggy incomplete features make using templates in D an unmitigated 
pain in the patushka.

I'd like to mention the main ones as I see it that appear to have been 
dropped on the floor in the hasty "rush to 1.0" and subsequent quixotic 
"quest for const".

-----------------------
1) Incomlete IFTI / type deduction:

1a) Numerous IFTI type deduction bugs
A quick bugzilla search on the term "IFTI" turned up the following 
unresolved IFTI issues
http://d.puremagic.com/issues/show_bug.cgi?id=493
http://d.puremagic.com/issues/show_bug.cgi?id=617
http://d.puremagic.com/issues/show_bug.cgi?id=756
http://d.puremagic.com/issues/show_bug.cgi?id=1454
http://d.puremagic.com/issues/show_bug.cgi?id=1650
http://d.puremagic.com/issues/show_bug.cgi?id=1807
http://d.puremagic.com/issues/show_bug.cgi?id=1848

And I know about this other one because I reported it:

http://d.puremagic.com/issues/show_bug.cgi?id=1661

There are probably others.  Basically, support for template parameter 
deduction is very poor, and it's quite easy to find cases where IFTI 
fails.  The problem is compounded by difficult-to-understand error 
messages from the compiler and lack of instantiation stack traces.

1b) *specialization* of any kind in D disables IFTI.  I had presumed 
this was just a temporary situation, but it shows no signs of getting 
any attention any time soon.  This one also makes it significantly more 
difficult to write template code in D than it is in C++.

1c) Furthermore, having only IFTI (i.e. functions only) is limiting, as 
well.  There's no reason why ICTI and ISTI (class and struct 
instantiation) shouldn't work.  For instance, if you make a class like
   class Class(T) {  this(T x) {} }
It should be possible to write    auto C = new Class(2.0f);
There is enough information there to deduce that it should instantiate 
Class!(float).  You can work around this by making factory functions, 
but why should that be necessary?

------------------------
2) Lack of Overloading:

The second big category of headaches comes from lack of overloading.

2a) Functions and templates.
You can't have a function and a template with the same name.  C++ has no 
problem with this.  I don't see why D should.  The workaround isn't 
terribly onerous, but then again neither should it be a terribly 
difficult fix, I suspect.

2b) Templates and templates
This is worse.  You can't overload templates with other templates of the 
same # of parameters even if the signatures are unambiguious.  This is 
where the infamous "dummy=void" hack comes in.

2c) No ADL:

Not being able to overload templates across modules kills user 
extensibility of templates.  It's a very common pattern in C++ code.  A 
generic class in a library uses Traits<T> to get info about a class.  If 
you make a new MyT, you can integrate your class into the lib by 
providing your own specialization of Traits!(MyT).  In D to get this you 
have to modify the original module where Traits! is defined.

It's like saying that to extend a class from a library you should edit 
the library's source code and add a member to the class there.  It is 
the antithesis of modular code.

I hope this will be fixed in D2 by the overload sets stuff, but I 
consider D1 broken for lack of this.

-

Yes, I know there are workarounds for most of these 1) and 2) issues -- 
believe me, I'm all too familiar with them -- but the problem is that in 
any significantly template heavy code, the workarounds touch just about 
every single function, and worse, force you to contort your code in ways 
that makes it hard to write and hard to maintain. (Everything turns into 
big opaque functions filled with static ifs:
     BigFunction(T...)(T args) {  /*heaps of static ifs*/ } )
Looking at that function signature tells you nothing, and it's 
significantly harder to write and maintain than the equivalent version 
using pattern matching on arguments various different specializations.

Finally 3) is something that I can't really call a bug, though I would 
sure like to:

-------------------
3) Lack of struct inheritance:
In most any significantly advanced template using library, you will find 
instances of the "Curiously Recurring Template Pattern" or CRTP. 
(http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern)

CRTP lets you do things like compile time polymorphism.

In my experience it is most used with value-type classes in C++ which 
make most sense as "struct" in D.

I hope the WalterAndrei.pdf proposal of using "alias SuperStruct this" 
will be able to support this.  Although I think it would be a lot easier 
on everyone if structs could just use the regular inheritance syntax and 
it was understood that because they are structs it is purely a 
non-virtual inheritance.

--bb



More information about the Digitalmars-d mailing list