"Value class instance" pattern?

bearophile bearophileHUGS at lycos.com
Sat Jul 13 05:47:27 PDT 2013


I don't know if this post is more fit for the main D newsgroup. 
In the end I have decided that it's better to ask here first.

Here inside every instance of Bar there is a reference to an 
instance of Foo:



abstract class Something {
     int spam(int);
}

class Foo : Something {
     int x;
     this(int xx) { x = xx; }
     override int spam(int x) { return x; }
}

class Bar : Something {
     Foo f;
     int y;
     this(Foo ff) { f = ff; }
     override int spam(int x) { return x; }
}

void main() {
     auto b = new Bar(new Foo(1));
}


In C++ class instances are values, so the class Bar can contain 
an instance of Foo as a value. This removes one allocation and 
one indirection and decreases a bit the pressure on the GC. How 
to do the same thing in D? Can I use Scoped or something to do 
that?

This is one solution I have found, to create a FooValue struct, 
and use Foo only as a wrapper:


abstract class Something {
     int spam(int);
}

struct FooValue {
     int x;
     this(int xx) { x = xx; }
     int spam(int x) { return x; }
}

class Foo : Something {
     FooValue f1;
     this(int xx) { f1.x = xx; }
     override int spam(int x) {
         return f1.spam(x);
     }
}

class Bar : Something {
     FooValue f2;
     int y;
     this(FooValue fv) { f2 = fv; }
     override int spam(int x) { return x; }
}

void main() {
     auto b = new Bar(FooValue(1));
}


But is this the best solution? (Beside containing some 
boilerplate code, calling Foo.spam requires a function call and a 
virtual call, instead of just a virtual call. Can we do with just 
one virtual call?).


Recently Andrei has suggested to create a Phobos wrapper (not yet 
implemented), I don't know if it's usable here:
http://d.puremagic.com/issues/show_bug.cgi?id=10404

If that wrapper will also allow derivation (as I have suggested) 
then I think it will allow shorter code like this (but I think 
this will keep needing a a function call and a virtual call to 
call Foo.spam):


import std.typecons: Class;

abstract class Something {
     int spam(int);
}

struct FooValue {
     int x;
     this(int xx) { x = xx; }
     int spam(int x) { return x; }
}

alias Foo = Class!(FooValue, Something);

class Bar : Something {
     FooValue f2;
     int y;
     this(FooValue fv) { f2 = fv; }
     override int spam(int x) { return x; }
}

void main() {
     auto b = new Bar(FooValue(1));
}


Bye and thank you,
bearophile


More information about the Digitalmars-d mailing list