Am 13.07.2013 17:15, schrieb bearophile:
(Sorry, this post has gone in this newsgroup by mistake, but it's a
small mistake.)


To change and understand your code a bit (now the ComposeClass
constructor is a template) I have removed some of the tests and debug
code, but they should be added back later:


/*
string listAvailableCtors(T)() {
     string result = "";
     foreach(t; __traits(getOverloads, T, "__ctor"))
         result ~= typeof(t).stringof ~ "\n";
     return result;
}
*/

struct DefaultCtor {} //call default ctor type
enum defaultCtor = DefaultCtor();

struct ComposeClass(T) if (is(T == class)) {
     void[__traits(classInstanceSize, T)] _classMemory = void;
     bool m_destructed = false;

     @property T _instance() {
         return cast(T)_classMemory.ptr;
     }

     @property const(T) _instance() const {
         return cast(const(T))_classMemory.ptr;
     }

     alias _instance this;

     @disable this();
     @disable this(this);

     this(DefaultCtor) {
         // _classMemory[] = typeid(T).init[]; // needed?
         _instance.__ctor;
     }

     this(Targs...)(Targs args) {
         _classMemory[] = typeid(T).init[];
         _instance.__ctor(args);
     }

     ~this() {
         if (!m_destructed) {
             _instance.destroy;
             m_destructed = true;
         }
     }
}

// Usage example ----------

class Foo {
     int i, j;
     this() {
         this.i = 5;
     }

     this(int ii) {
         this.i = ii;
     }
}

class Bar {
     ComposeClass!Foo f;

     this() {
         //f = typeof(f)(defaultCtor);
         f = typeof(f)(2); // alternative
     }
}

void main() {
     import std.stdio;
     auto bar = new Bar;
     writeln(bar.f.i);
     bar.f.i = 1;
     writeln(bar.f.i);
}


This code is unfinished.
Is the assignment needed in this(DefaultCtor)?

This code contains some sharp edges (for the D programmer and even for
the compiler, I have opened a new bug report:
http://d.puremagic.com/issues/show_bug.cgi?id=10629 ), for me it's easy
to get wrong, hard to get right & good, and I believe it's of general
usefulness, so I think it's fit for Phobos.

But isn't it a replacement for Phobos Scoped?

Bye,
bearophile

Yes the assignment in this(DefaultCtor) is needed, because the construction process of a D object is defined as:

1) Initialize memory with T.init
2) Call the constructor

You can test that with a class that looks as follows

class Foo
{
  int i = 5;
  this() { assert(i == 5); }
}

I really like the constant defaultCtor value idea which makes the usage somewhat nicer. The debugging values are needed because most debuggers won't be able to evaluate properties while debugging.

Yes this looks pretty similar to scoped in phobos but I always thought that scoped was inteded for objects to be placed on the stack instead of inside other objects. Thats also why scoped does some additional alignment which is garantueed when you do it within a class.

Also from reading the sourcecode of scoped, doesn't the address of the scoped object change between construction and destruction? Because it is created inside the scoped function and then returned, which will do a move. And then later destroyed at its final destination. Wouldn't that break with interior pointers?

Kind Regards
Benjamin Thaut

Reply via email to