Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
a local clone.

Templates Revisited

What I am going to tell you about is what we teach our programming students in
the third or fourth year of graduate school... It is my task to convince you not
to turn away because you don't understand it. You see my programming students
don't understand it... That is because I don't understand it. Nobody does.
Richard Deeman

Templates in C++ have evolved from little more than token substitution into a
programming language in itself. Many useful aspects of C++ templates have been
discovered rather than designed. A side effect of this is that C++ templates are
often criticized for having an awkward syntax, many arcane rules, and being very
difficult to implement properly. What might templates look like if one takes a
step back, looks at what templates can do and what uses they are put to, and
redesign them? Can templates be powerful, aesthetically pleasing, easy to
explain and straightforward to implement?
This article takes a look at an alternative design of templates in the D
Programming Language [1].

The first thing that comes to mind is the use of < > to enclose parameter
lists and argument lists. < > has a couple serious problem, however.
They are ambiguous with operators <, >, and >>. This means that expressions
like:

a<b,c>d;

and:

a<b<c>>d;

are syntactically ambiguous, both to the compiler and the programmer.
If you run across a<b,c>d; in unfamiliar code, you've got to slog through
an arbitrarily large amount of declarations and .h files to figure out
if it is a template or not.
How much effort has been expended by programmers, compiler writers, and
language standard writers to deal with this?

There's got to be a better way. D solves it by noticing that ! is not used
as a binary operator, so replacing:

a<b,c>

with:

a!(b,c)

is syntactically unambiguous. This makes it easy to parse, easy to generate
reasonable error messages for, and makes it easy for someone inspecting the
code to determine that yes, a must be a template.

POD (Plain Old Data, as in C style) structs
bring together related data declarations, classes bring together
related data and function declarations, but there's nothing to logically group
together templates that are to be instantiated together.
In D, we can write:

C++ templates can be in the form of a template declaration, a template
definition, and an exported template.
Because D has a true module system, rather than textual #include files,
there are only template definitions in D. The need for template declarations
and export is irrelevant. For example, given a template definition in
module A:

Partial and explicit specialization work as they do in C++, except that
there is no notion of a ‘primary’ template. All the templates with the
same name are examined upon template instantiation, and the one with the
best fit of arguments to parameters is instantiated.

C++ has some unusual rules for name lookup inside templates, such
as not looking inside base classes, not allowing scoped redeclaration
of template parameter names, and not considering overloads that
happen after the point of definition (this example is
derived from one in the C++98 Standard):

Template recursion combined with specialization means that C++ templates
actually form a programming language, although certainly
an odd one. Consider a set of templates that computes a factorial at
run time. Like "hello world" programs, factorial is the canonical example
of template metaprogramming:

reducing 13 lines of code to an arguably much cleaner 7 lines.
static if's are the equivalent of C++'s #if.
But #if cannot access template
arguments, so all template conditional compilation must be handled with
partial and explicitly specialized templates.
static if dramatically simplifies
such constructions.

D can make this even simpler. Value generating templates such
as the factorial one are possible, but it's easier to just write
a function that can be computed at compile time:

Template IsFunctionT relies on two side effects to achieve its result.
First, it relies on arrays of functions being an invalid C++ type.
Thus, if U is a function type, the second test will not be selected
since to do so would cause an error (SFINAE (Substitution Failure Is Not An Error)).
The first test will be selected.
If U is not a function type, the second test is a better fit than ... .
Next, it is determined which test was selected by examining the size
of the return value, i.e. sizeof(One) or sizeof(Two).
Unfortunately, template metaprogramming in C++ often seems to be relying
on side effects rather than being able to expressly code what is desired.

The is(T[]) is the equivalent of SFINAE (Substitution Failure Is Not An Error).
It tries to build an array of T,
and if T is a function type, it is an array of functions. Since this is
an invalid type, the T[] fails and is(T[]) returns false.

Literal square roots are often needed for speed reasons in other runtime
floating point computations, such as computing the gamma function.
These template floating point algorithms need not be efficient as they are
computed at compile time, they only need to be accurate.

Much more complex templates can be built, for example, Don Clugston
has written a template to compute π at compile time. [2]

Again, we can just do this with a function that can be executed
at compile time:

How do D templates fare with something much more significant, like
a regular expression compiler? Eric Niebler has written one for C++
that relies on expression templates. [4]
The problem with using expression templates is that one is restricted
to using only C++ operator syntax and precedence.
Hence, regular expressions using expression templates don't look like
regular expressions, they look like C++ expressions.
Eric Anderton has written one for D that relies on the ability of
templates to parse strings. [5]
This means that, within the strings, one can use the expected regular
expression grammar and operators.

The regex compiler templates parse the regex string argument,
pulling off tokens
one by one from the front, and instantiating custom template functions
for each token predicate,
eventually combining them all into one function that directly implements
the regular expression.
It even gives reasonable error messages for syntax errors in
the regular expression.

Calling that function with an argument of a string to match returns
an array of matching strings: