C++ templates have grown to be language within a language, at least
for some users. Do most programmers overuse templates? Given that C++
template techniques, and some of them are quite intricate, can lock in
an entire codebase (that is, require a ground-up re-implementation if
wanting to use another, perhaps new, language), is extreme template
use wrought with peril in the long term view of things? Is a policy
that requires "judicious" use of templates the way to go?
I think templates (generics) are a concept which is okay, but should
be improved.
I have a special view of templates:
Templates are a concept to execute something at compile time
instead of runtime. I am talking about the template instantiation
which means that the compiler inserts template parameters and
generates function (and other) definitions.
I view the template itself as just a kind of function. A template is
a function which can have types as parameters and which is executed
at compile time instead of runtime. The execution of a template at
compile time is called template instanciation.
The question is: Why do templates definitions require a syntax which
is totally different from function definitions. Other than just
being called at compile time, the possibility to have types as
parameters and a function body which contains function definitions
(for functions which should be defined when the template is
instantiated), there is no difference.
I dont know how such template generating functions could be
introduced to C++. Therefore I refrain to write examples how
code like this would look like in C++.
Instead I can show examples how this is done in a different
language. The templates/generics introduced in Seed7 just work in
the way outlined above. The 'DEFINE_MAX' template, to create the
'max' function for different types, is defined with:
const proc: DEFINE_MAX (in type: aType) is func
begin
const func aType: max (in aType: a, in aType: b) is func
result
var aType: result is aType.value;
begin
if a > b then
result := a;
else
result := b;
end if;
end func;
end func;
The body of the 'DEFINE_MAX' function contains just a normal
definition of a 'max' function for the type 'aType'. The type
'aType' is introduced as parameter of the function 'DEFINE_MAX'.
The parameter 'aType' has the type 'type'. It is necessary to
instantiate the 'DEFINE_MAX' function (template) explicit:
DEFINE_MAX(integer);
DEFINE_MAX(char);
DEFINE_MAX(string);
Note that it is necessary that the operator '>' is defined for
all types which are used in an instantiation of 'DEFINE_MAX'.
An attempt to instantiate the 'DEFINE_MAX' function (template)
with a type, where the '>' operator is missing, results in a
compile time error.
A function (template), which is capable to define 'for' statements
for different types, is explained here:
http://seed7.sourceforge.net/examples/for_decl.htm
Even abstract data types can be defined with functions (templates).
This is done in the follwing way:
An abstract data type is defined by a function (template) which
returns a type that was generated by the function. Additionally
the function (template) contains definitions for functions which
are useable for the new type. This way container types like
'array' or 'hash' can be defined.
You may argue that the C++ templates can do this also (by using
a different notation). But Seed7 templates are much more powerful,
because the can contain any code and not just function definitions.
That way 'if' statements inside the template can decide which
functions should be defined. This allows a 'set' type which is
implemented with bitsets or hash tables, dependent on the
capabilities of the base type. E.g.: Types like 'char' and 'boolean'
can be converted to integers and therefore a bitset implementation
is possible. OTOH types like 'string' have no ordinal number and
therefore hash tables are used to implement a 'set'.
I hope that my explanation gives a modern view at templates.
Greetings Thomas Mertes
Seed7 Homepage:
http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.