"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