const debacle
e-t172
e-t172 at akegroup.org
Sat Mar 22 04:21:24 PDT 2008
Janice Caron a écrit :
> Why am I suggesting this? Well, bear with me. All will become clear
> shortly. The next step is to introduce a new kind of template
> parameter:
>
> template T(const K)
> {
> ...
> }
The problem of this solution is that you're basically using templates to
solve a problem which will probably affect a LOT of functions
(especially text processing functions).
I think we should keep in mind that :
- most of libraries are distributed in shared form (at least on Unix),
because shared libraries are far more practical;
- templates themselves cannot be compiled, so they cannot be included
in a shared library, they are "compiled" when the code that instanciates
them is compiled (which basically is the same as using static libraries)
This means that when you are over-using templates, you lose all the
advantages of shared libraries. I think a lot of people easily forget
about this; for example, in Tango text.Util:
T[] trim(T) (T[] source)
T[] strip(T) (T[] source, T match)
T[][] split(T) (T[] src, T[] pattern)
etc... nearly all functions in this module are templates, in order to
support char, dchar and wchar without duplicating code. This basically
means that when we'll be able to compile Tango in a shared library, this
module will be compiled to... nothing. This means that when the code of
this module is modified, ALL projects using it must be recompiled to use
the new module. Now imagine that D become very popular (which I hope
will happen), this will become very hard to manage (if you don't
understand why, imagine what would happen if the libc was linked
statically in all executables of your system...)
In the case of Tango, we can address this issue by writing this in
text.Util:
char[] trim(char[] source) { return trim!(char)(source); }
dchar[] trim(dchar[] source) { return trim!(dchar)(source); }
wchar[] trim(wchar[] source) { return trim!(wchar)(source); }
And so on for all functions. However, it is not very elegant. A better
idea would be to include a new "feature" in D 2.0, i.e. "compiled
templates", with a new syntax like this :
T[] trim(T # [char,dchar,wchar]) (T[] source)
This will behave exactly like the original syntax, except that when you
compile text.Util, trim() will be included in the object file in three
versions: char, dchar and wchar. Now when the caller writes
trim!(char)(foo), the compiler WILL automatically use the already
compiled "char" version of trim(). And if you want to do something
exotic, like trim!(mytype)(foo), it will still be possible, but it will
behave like a "classic" template, that is, the template code will be
compiled into the code that instanciates it.
The point here is to allow the compiler to generate object code for
templates which get only used with a small subset of types 99% of the
time (like these functions in Tango, which are only used with char,
dchar and wchar), in order to render shared libraries more useful and
practical.
Of course, "pure templates", that is, templates which are meant to be
instanciated and used with any given type as parameter, cannot benefit
from this "feature".
So, back to the point, in your case :
> template T(const K)
> {
> K char[] f(K char[] buf ) { ... }
> }
Would become :
template T(const K # [auto,const,invariant])
{
K char[] f(K char[] buf ) { ... }
}
A better solution: each "const K" template construct is always compiled
in the three versions (or rather in one version, because the object code
for the three is identical).
More information about the Digitalmars-d
mailing list