Templates - What's Up with the template keyword?

Alex AJ at gmail.com
Tue Apr 9 14:41:30 UTC 2019


On Monday, 8 April 2019 at 12:23:28 UTC, Ron Tarrant wrote:
> I'm digging into templates in an attempt to understand the 
> signals-n-slots replacement for the observer pattern, but I've 
> got a question I can't seem to find an answer for and an 
> example for which I'm unable to solve the error.
>
> First, the question...
>

Your confusion arises in your understanding of meta programming 
and templates. Templates are compile time expressions that use 
parameters. They are exactly analogous to parameters in typical 
programming but allow one to pass around CT information that 
doesn't exist at run time.

It is not the statement itself that is a template but the fact 
that it depends on a "template", which is a sort of abstract 
variable.

class C(T)

template C(T)

struct(T)

interface(T)

void foo(T)()

etc...


are all things that depend on a template parameter T. One can say 
that they are all "templated" or are "templates".

One can also say they are parameterized(meaning they take a 
parameter, but the parameters are CT "objects".


Essentially template is the most general and the rest are just 
syntactic sugar.

e.g.,

template CC(T)
{
    class C
    {
       T t;
    }
}


template CC is a "template"(just like a cookie cutter but that 
can configure itself depending on what T is, as this example 
shows that we can create a class with different type of t.


D has all kinda of stuff like this that help reduce the bloat of 
templates. Sometimes you must use one method over another for 
certain effects but usually you can pick and choose.

The idea is not to think of meta programming as something 
different than normal programming. It is still programming and 
there is enough of an overlap that it benefits one to realize 
they are the same thing but are at different levels in the type 
system. Meta programming works on the type hierarchy while 
"runtime programming" works in the type hierarchy. Meta 
programming is a super set of runtime programming.


The way I think of meta programming is that of coding runtime 
code. Run time code codes binary code. If I create a statement 
like

writeln("test");

I know that the code gets translated in to a call instruction, 
pointers are used, "test" exists in some location in memory, 
etc... it all is machine code though when I compile.

When I do something like this

foo!int();

I know that the first part of foo!int is "meta code" and it first 
gets translated in to runtime code and then that code gets 
translated in to machine code.

For example

void foo(T)(T s) { writeln(s); }

in this case, depending on what T is at compile time(which I get 
to decide in some way and so I know exactly what it is at compile 
time, in theory), foo takes on different versions.

if I call foo(3) then it is writeln(3) and T is an int(by 
deduction in the compiler) and the compiler can even optimize out 
certain things here because it also knows that 3 is known.(this 
is CTFE) There is nothing to optimize in that example though.

if I call foo(readln()) then the the compiler cannot optimize out 
but this code get translated in to writeln(readlin()) but T is a 
string(since readln returns a string and the compiler can deduce 
it).

But in general foo acts as all these possibilities(and all the 
possibilities are known by the compiler because they have to be 
known to compile and use).

So, what does templates do? They combine very similar code in to 
meta blocks that can then be easily used. They allow constructing 
very complex meta code such as

void foo(T)(T s) { static if (is(T == string)) writeln(s); }


and now foo is much more complicated because it has two 
completely different behaviors depending on what T is. You can't 
get that with run time code without a lot of work and it will 
never be efficient. But here the compiler will eventually know 
what T is and it can then choose the correct path at compile 
time. The if will disappear and so no extra overhead exists at 
runtime.

So, templates are very powerful things(the above doesn't even 
dent their power) The idea to bear in mind is that anything in D 
is a template if it takes a template parameter. Think of a 
template as a drawing template used to sketch something. It isn't 
the final result but it shapes the final result. It is more like 
a blueprint or a program in and of itself.

I think the hard part for many is that they can't balance the 
meta programming part with the run time part. This is very easy 
though if one always just keeps track of which side one is 
programming in and not to mix them up(mentally).

The meta programming part will always be obvious, it will depend 
on template parameters and use meta programming constructs. There 
are sometimes overlap between the two levels but it because 
natural once one gets enough of an understanding.

The hardest part about D is that it has so much meta programming 
stuff and there are sometimes bugs and special cases to do 
things, but the grammatical design of it's type system is very 
nice and sane compared to most other procedural programming 
languages.


Always keep in mind that the templating system is about creating 
"generic" code. source code that generates source code(D could 
spit out a non-templated source code version if it was designed 
to) which then generates machine code.

Each higher level allows one to organize levels below it and 
create generic solutions to problems.

Ideally we would have even higher levels but programmers haven't 
evolved to this point yet(maybe some functional languages have).





More information about the Digitalmars-d-learn mailing list