"Value class instance" pattern?

Benjamin Thaut code at benjamin-thaut.de
Sat Jul 13 09:19:07 PDT 2013


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



More information about the Digitalmars-d mailing list