clear()

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Oct 9 09:40:43 PDT 2009


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));
     }
}



More information about the Digitalmars-d mailing list