On 2/12/15 11:01 PM, Jakob Ovrum wrote:
On Thursday, 12 February 2015 at 12:59:39 UTC, Steven Schveighoffer wrote:
I think given the necessity of the above (which was not discussed or
noticed in that bug report), we should add a way to call the true
destructor properly in the compiler.
I think these do the right thing with only marginal overhead:
---
void destructRecurse(S)(ref S s)
if (is(S == struct))
{
static if (__traits(hasMember, S, "__dtor"))
s.__dtor();
foreach_reverse (ref field; s.tupleof)
{
alias Field = typeof(field);
static if (is(Field == struct) && hasElaborateDestructor!Field)
destructRecurse(field);
}
}
void postblitRecurse(S)(ref S s)
if (is(S == struct))
{
foreach (ref field; s.tupleof)
{
alias Field = typeof(field);
static if (is(Field == struct) &&
hasElaborateCopyConstructor!Field)
postblitRecurse(field);
}
static if (__traits(hasMember, S, "__postblit"))
s.__postblit();
}
---
I notice now it is missing proper handling of fixed-length arrays: I'll
add that. Anything else missing?
Efficiency-wise they should at least be a lot better than the status quo
- two indirect calls. For absolutely optimal performance it relies on
the inliner, but if it is demonstrated to be a problem compared to the
compiler-generated solution, it could always generate optimal code with
some hands-on string mixins :)
I am aware that std.traits is not available in object_.d - the
hasElaborate* templates are fairly simple and easy to reimplement.
Thanks, but I wonder, aren't we simply duplicating what the compiler
does? It seems kind of wasteful to have 2 identical functions. Plus, if
any behavior changes, I'd rather have one place to change it. Last thing
we need is subtle differences between builtin destruction and explicit
destruction.
I really think either the compiler should be redirected to call this
function (ideal) or we should be able to call the compiler function
directly.
-Steve