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.

-Steve

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.

Reply via email to