Templates everywhere
Max Samukha
spambox at d-coding.com
Mon Mar 15 05:20:24 PDT 2010
On 15.03.2010 3:42, Walter Bright wrote:
> Bane wrote:
>>> ======= C++ =========
>>> template<class T> class Foo
>>> {
>>> T member;
>>> };
>>> ======= D ===========
>>> class Foo(T)
>>> {
>>> T member;
>>> }
>>> =====================
>>>
>>> Yes, it looks like a trivial change, and perhaps it is. But it makes
>>> a world of difference, because it now looks like something I do get -
>>> a parameter list to something.
>>
>> Fucking beautiful. I finally get it.
>
>
> Ya know what's funny? I had to go and double check that the C++ syntax
> above was correct. Didn't have to do that for D.
Though I love D's templates:
1. People tend to throw them in where a runtime solution would suffice.
One example is an overload of 'clear' in the D runtime:
void clear(T)(T obj) if (is(T == class))
{
auto defaultCtor =
cast(void function(Object)) obj.classinfo.defaultConstructor;
version(none) // enforce isn't available in druntime
_enforce(defaultCtor || (obj.classinfo.flags & 8) == 0);
immutable size = obj.classinfo.init.length;
static if (is(typeof(obj.__dtor())))
{
obj.__dtor();
}
auto buf = (cast(void*) obj)[0 .. size];
buf[] = obj.classinfo.init;
if (defaultCtor)
defaultCtor(obj);
}
Since the function uses runtime information (except for the destructor),
it is absolutely unnecessary to instantiate the template for each
concrete class type. A more severe problem with the code above,
unrelated to templates, is that base class destructors are not called.
Here is a non-template implementation that should fix the problems (it
is a template but only formally):
void clear(Dummy = void)(Object obj)
{
auto ci = obj.classinfo;
auto defaultCtor =
cast(void function(Object)) ci.defaultConstructor;
version(none) // enforce isn't available in druntime
_enforce(defaultCtor || (ci.flags & 8) == 0);
immutable size = ci.init.length;
auto ci2 = ci;
do
{
auto dtor = cast(void function(Object))ci2.destructor;;
if (dtor)
dtor(obj);
ci2 = ci2.base;
} while (ci2)
auto buf = (cast(void*) obj)[0 .. size];
buf[] = ci.init;
if (defaultCtor)
defaultCtor(obj);
}
BTW, I do think that base class destructor calls not compiled directly
into derived class destructors is a mistake.
2. Templates impose functional style on programmers (see Bartosz's rant
at
http://bartoszmilewski.wordpress.com/2009/10/21/what-does-haskell-have-to-do-with-c/).
More information about the Digitalmars-d
mailing list