Templates - What's Up with the template keyword?

Adam D. Ruppe destructionator at gmail.com
Mon Apr 8 12:40:10 UTC 2019


On Monday, 8 April 2019 at 12:23:28 UTC, Ron Tarrant wrote:
> But in "Programming in D," (self, 2009-2018) by Ali Çehreli, 
> there's no mention of the 'template' keyword in any of his 
> examples.

You don't need template keyword for the majority of cases because 
the compiler lets you do shortcuts.

If you write

void foo(T)(int a) {}

the compiler sees that as a shortcut of writing

template foo(T) {
   void foo(int a) {}
}

and does all the necessary expansion for you.

Writing long-form templates is for when you need to do it more 
advanced topics. Like a template is allowed to have several 
members if you write it long-form. You can also use it to force a 
specific strategy like CTFE inside the template (though the 
compiler now has shortcuts for that too, so you don't see it 
written long-form much more in new code).


> Point!T getResponse(T : Point!T)(string question)

This looks wrong...

getResponse(T : Point)

should work (and is what I see in the book), but `T : Point!T` is 
different.


So what the colon does is specialize the template - it says "if 
you pass a type matching `Point` (the stuff after the colon), use 
this function instead of the generic function".

The reason `T : Point!T` isn't compiling is that that's saying 
only match a recursive template... and you don't have one of 
those.


You probably are thinking something along the lines of

Point!T getResponse(T : Point!R, R)(string question) {}

(maybe I am looking at the wrong part of the book, it is hard to 
find the right section/page number online). This is one of the 
most advanced template forms which is able to deconstruct other 
templates.

So, if you call that with a

Point!int p;

getResponse!(typeof(p))("my question")

then it will match T as being some kind of `Point!R`... and it 
will take apart the R into its own argument.

So when given Point!int, it will see the part after ! happens to 
be int, and make R == int.

Thus, inside the getResponse function:

T == Point!int
R == int

and you can inspect that and react accordingly. Or you can ignore 
the R and just use the Point. The value here is you could pass 
Point!int or Point!float or Point!whatever all to the one 
function.

(You can also do this if you just use an unrestricted T argument, 
but the Point!R specialization will make the intent more clear in 
documentation and lets you take it apart if you need to know what 
R is.)


More information about the Digitalmars-d-learn mailing list