Reset all Members of a Aggregate Instance
Chris Wright via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Dec 3 14:32:32 PST 2015
On Thu, 03 Dec 2015 21:55:04 +0000, Nordlöw wrote:
> On Thursday, 3 December 2015 at 21:38:48 UTC, Chris Wright wrote:
>> The terrible way is something like:
>>
>> void reset(Object o)
>> in {
>> assert(!(o is null));
>> }
>> body {
>> auto p = cast(ubyte*)*cast(void**)&o;
>> auto ci = o.classinfo;
>> auto init = cast(ubyte)ci.init; p[0..init.length] = init[];
>> if (ci.defaultConstructor) {
>> ci.defaultConstructor(o);
>> } else {
>> throw new Exception("no default constructor; object is in
>> invalid state");
>> }
>> }
>
> In what way is this better than my solution?
I called my solution "terrible", which doesn't suggest that I think well
of it compared to alternatives. I did this mainly to provide another
implementation that someone else had alluded to. But since you asked...
You're ignoring the distinction between runtime and compiletime types,
and you are resetting fields to the default values of their types, not
the default values of the fields.
To wit:
class Foo {
int i = 5;
}
class Bar : Foo {
int j = 6;
this() {}
this(int a, int b) { i = a; j = b; }
}
Foo foo = new Bar(10, 10);
nordlow.resetAllFields(foo);
We expect foo to look like a default-initialized instance of whatever it
began life as. Like if we implemented the equality operations, we'd
expect to see this work: `assert(foo == new Bar);` But we don't. Your
solution doesn't know what the default field value of Foo.i is, so it
erroneously resets it to 0. We wanted 5.
Similarly, your solution ignores the fact that we've got an instance of
Bar here, not an instance of Foo, and there are additional fields that
need to be reset. You're using compile time reflection, so there's no way
around that -- unless you create a virtual method with a mixin and
require the user to mix it into each class in the hierarchy.
My solution still gets a ton wrong. I forgot to call the destructor, for
instance. I can't call the constructor if it has parameters, and that
means the object might well be in an invalid state. It's not safe in the
face of potential runtime changes.
Assuming I encountered a case that both our solutions could handle
correctly, I'd prefer yours. It's safer.
More information about the Digitalmars-d-learn
mailing list