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