Templates - What's Up with the template keyword?

Ali Çehreli acehreli at yahoo.com
Wed Apr 10 00:42:11 UTC 2019


On 04/08/2019 05:59 AM, Ron Tarrant wrote:
> On Monday, 8 April 2019 at 12:40:10 UTC, Adam D. Ruppe wrote:
> 
>> You don't need template keyword for the majority of cases because the 
>> compiler lets you do shortcuts.
> Thanks, Adam. Good to know.
> 
> 
>> (maybe I am looking at the wrong part of the book, it is hard to find 
>> the right section/page number online).
> 
> My bad. The edition I'm working from was released 2018-10-17 and can be 
> found here:
> 
> http://ddili.org/ders/d.en/Programming_in_D.pdf
> 
> The page number in online PDF viewer is 421 and the example is about 1/3 
> of the way down the page.
> 
>
That template specialization works along with the general definition of 
the same template. So, you must have the following function template as 
well:

T getResponse(T)(string question) {
     writef("%s (%s): ", question, T.stringof);

     T response;
     readf(" %s", &response);

     return response;
}

As Steve said, when you replace all Ts in there e.g. with int, you get 
what the compiler would generate for T being int. However, the readf 
above cannot work with e.g. Point!double because readf does not know 
what Point!double is. For that reason, we may use a specialization for 
Point!T:

Point!T getResponse(T : Point!T)(string question)
{
     writefln("%s (Point!%s)", question, T.stringof);

     auto x = getResponse!T(" x");
     auto y = getResponse!T(" y");

     return(Point!T(x, y));

} // getResponse() Point!T

(It may be made to work with Adam's (T : Point!R, R) syntax but I failed 
just now.)

Now you have a specialization that works with any Point!T. T can be 
double, int, etc. However, you must call getResponse with that special 
Point. I'm using an alias for code reduction:

   alias MapLocation = Point!double;
   auto wayPoint1 = getResponse!MapLocation("Where is the first map 
location?");
   auto wayPoint2 = getResponse!MapLocation("Where is the second map 
location?");

Your code did not work because Point is not a type but a type template. 
(On the other hand, Point!double is a type). The whole program:

import std.stdio;
import std.math;
import std.string;

struct Point(T)
{
     T x;
     T y;

     T distanceTo(Point that) const
     {
         immutable real xDistance = x - that.x;
         immutable real yDistance = y - that.y;

         immutable distance = sqrt((xDistance * xDistance) + (yDistance 
* yDistance));

         return(cast(T)distance);

     } // distanceTo()

} // struct Point

T getResponse(T)(string question) {
     writef("%s (%s): ", question, T.stringof);

     T response;
     readf(" %s", &response);

     return response;
}

Point!T getResponse(T : Point!T)(string question)
{
     writefln("%s (Point!%s)", question, T.stringof);

     auto x = getResponse!T(" x");
     auto y = getResponse!T(" y");

     return(Point!T(x, y));

} // getResponse() Point!T


void main()
{
   alias MapLocation = Point!double;
     auto wayPoint1 = getResponse!MapLocation("Where is the first map 
location?");
     auto wayPoint2 = getResponse!MapLocation("Where is the second map 
location?");

     writeln("Distance: ", wayPoint1.distanceTo(wayPoint2));

} // main()

Ali


More information about the Digitalmars-d-learn mailing list