Andrei Alexandrescu wrote:
I think this has been discussed in this group already.
An object storing another object needs two allocations:
class A { ... }
class B {
A a;
this() {
a = new A;
}
}
auto b = new B; // two allocations
I'm thinking of using "scope" in this situation to imply in-situ storage:
class B {
scope A a;
this() {
a = new A;
}
}
Now the A member actually lies inside of B - no more indirection. That
means the constructor needs special scrutiny, in particular a cannot be
null because that wouldn't make much sense.
What do you think?
I think it should be done in userland, not built-in. Here's a
proof-of-concept implementation:
----
import std.stdio;
string scopeInstance(string type, string name) {
return `
private byte[__traits(classInstanceSize, `~type~`)]
_scopeInstance__`~name~`;
static this() {
const int off = _scopeInstance__`~name~`.offsetof;
const int len = __traits(classInstanceSize, `~type~`);
typeof(this).classinfo.init[off .. off + len] =
`~type~`.classinfo.init;
}
`~type~` `~name~`() {
return cast(`~type~`)_scopeInstance__`~name~`.ptr;
}
void `~name~`(`~type~` f) {
_scopeInstance__`~name~`[] =
(cast(byte*)f)[0.._scopeInstance__`~name~`.sizeof];
}`;
}
class Foo {
int x;
float y;
string zomg = "zomg";
this(int x, float y) {
writeln("making a Foo");
this.x = x;
this.y = y;
}
~this() {
writeln("death-tracting a Foo");
}
}
class Bar {
string x;
this (string x) {
writeln("making a Bar");
this.x = x;
}
}
class Baz {
mixin(scopeInstance("Foo", "foo"));
mixin(scopeInstance("Bar", "bar"));
this() {
writeln("making a Baz");
foo.__ctor(1, 3.14f);
bar.__ctor("ohai");
}
~this() {
writeln("death-tracting a Baz");
foo.__dtor();
}
}
void main() {
scope b = new Baz;
writeln(b.foo.x, " ", b.foo.y, " ", b.foo.zomg);
writeln(b.bar.x);
writeln("Foo size: ", __traits(classInstanceSize, Foo));
writeln("Bar size: ", __traits(classInstanceSize, Bar));
writeln("Baz size: ", __traits(classInstanceSize, Baz));
}
----
Result:
----
making a Baz
making a Foo
making a Bar
1 3.14 zomg
ohai
Foo size: 24
Bar size: 16
Baz size: 48
death-tracting a Baz
death-tracting a Foo
----
Now for a brief summary:
* I couldn't get hold of the initializer of a class at compile-time.
I've tried using symbol.mangleof ~ "6__initZ", but DMD told me it could
not be an initializer for a static array. This forced me to initialize
the 'inline' / 'scope' class instances in a static ctor. I'm not sure if
this is legal - can ClassInfo ever wind up to live in ROM? Perhaps
__traits(classInitializer, _) could be added.
* The long proposed __ident extension would allow turning the string
mixin into a regular template mixin.
* __ctor should be standardized (or is it?)
I'm not very good at D2, so perhaps there are better ways to implement
it by now. Here's a similar proposal in pseudo-D2-code:
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=85684
--
Tomasz Stachowiak
http://h3.team0xf.com/
h3/h3r3tic on #D freenode