I'm talking with Sean and Walter about taking the first step towards eliminating delete: defining function clear() that clears the state of an object. Let me know of what you think.

One problem I encountered is that I can't distinguish between a default constructor that doesn't need to exist, and one that was disabled because of other constructors. Consider:

class A {}
class B { this(int) {} }

You can evaluate "new A" but not "new B". So it's legit to create objects of type A all default-initialized. But the pointer to constructor stored in A.classinfo is null, same as B.

Any ideas?


Andrei

===============================

void clear(T)(T obj) if (is(T == class))
{
    auto defaultCtor =
        cast(void function(Object)) obj.classinfo.defaultConstructor;
    enforce(defaultCtor);
    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;
    defaultCtor(obj);
}

unittest
{
    {
        class A { string s = "A"; this() {} }
        auto a = new A;
        a.s = "asd";
        clear(a);
        assert(a.s == "A");
    }
    {
        static bool destroyed = false;
        class B {
            string s = "B";
            this() {}
            ~this() {
                destroyed = true;
            }
        }
        auto a = new B;
        a.s = "asd";
        clear(a);
        assert(destroyed);
        assert(a.s == "B");
    }
    {
        class C {
            string s;
            this() {
                s = "C";
            }
        }
        auto a = new C;
        a.s = "asd";
        clear(a);
        assert(a.s == "C");
    }
}

void clear(T)(ref T obj) if (is(T == struct))
{
    static if (is(typeof(obj.__dtor())))
    {
        obj.__dtor();
    }
    auto buf = (cast(void*) &obj)[0 .. T.sizeof];
    auto init = (cast(void*) &T.init)[0 .. T.sizeof];
    buf[] = init[];
}

unittest
{
    {
        struct A { string s = "A";  }
        A a;
        a.s = "asd";
        clear(a);
        assert(a.s == "A");
    }
    {
        static bool destroyed = false;
        struct B
        {
            string s = "B";
            ~this()
            {
                destroyed = true;
            }
        }
        B a;
        a.s = "asd";
        clear(a);
        assert(destroyed);
        assert(a.s == "B");
    }
}

void clear(T : U[n], U, size_t n)(/*ref*/ T obj)
{
    obj = T.init;
}

unittest
{
    int[2] a;
    a[0] = 1;
    a[1] = 2;
    clear(a);
    assert(a == [ 0, 0 ]);
}

void clear(T)(ref T obj)
        if (!is(T == struct) && !is(T == class) && !isStaticArray!T)
{
    obj = T.init;
}

unittest
{
    {
        int a = 42;
        clear(a);
        assert(a == 0);
    }
    {
        float a = 42;
        clear(a);
        assert(isnan(a));
    }
}

Reply via email to