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.)

Reply via email to