classes by value

Dgame r.schuett.1987 at gmail.com
Thu Dec 14 14:45:51 UTC 2017


On Thursday, 14 December 2017 at 14:31:33 UTC, Jonathan Marler 
wrote:
> Thought I would share this little nugget.  It's a simple module 
> to enable "classes by value".  A good demonstration of the 
> power of "alias this". I had originally implemented this using 
> "opDispatch" and only after I was done did I realize I could 
> have made my life much simpler if I had gone with "alias this" 
> in the first place :)
>
> https://run.dlang.io/gist/marler8997/799286523e139c65c6de1b37b6729a72?compiler=dmd&args=-unittest%20-main
>
> /**
> Value is a template that represents a class object value.  This 
> is in contrast to a
> normal class object which is a pointer to a class object value.
>
> ---
> void foo(Value!SomeClass value)
> {
>     // ... use value
> }
> ---
> */
> struct Value(T) if (is(T == class))
> {
>     @disable this();
>     private void[__traits(classInstanceSize, T)] ____classdata 
> = void;
>     @property pragma(inline) T ____classptr()
>     {
>         return cast(T)&this;
>     }
>
>     alias ____classptr this;
> }
> /**
> Initializes a class value
> */
> void initClassValue(T, Args...)(Value!T* classValue, Args args) 
> if (is(T == class))
> {
>     import std.conv : emplace;
>
>     emplace(classValue.____classptr, args);
> }
> /**
> Use to create a class object value.
> ---
> auto classValue = createClasValue!SomeClass;
> ---
> */
> Value!T createClassValue(T, Args...)(Args args) if (is(T == 
> class))
> {
>     import std.conv : emplace;
>
>     Value!T value = void;
>     emplace(value.____classptr, args);
>     return value;
> }
>
> /**
> Creates a Value!T class from class T.
> ---
> Foo foo; // foo is a class
>
> Value!Foo fooValue1 = void;
> copyClassValue(&fooValue1, classObject);
>
> auto foo2 = foo.copyClassValue();
> ---
> */
> void copyClassValue(T)(Value!T* classValue, T classObject) if 
> (is(T == class))
> {
>     classValue.____classdata[0 .. __traits(classInstanceSize, 
> T)] =
>         (cast(ubyte*) classObject)[0 .. 
> __traits(classInstanceSize, T)];
> }
> /// ditto
> Value!T copyClassValue(T)(T classObject) if (is(T == class))
> {
>     Value!T value = void;
>     copyClassValue(&value, classObject);
>     return value;
> }
>
> unittest
> {
>     static class Foo
>     {
>         int x;
>         this(int x)
>         {
>             this.x = x;
>         }
>
>         void assertValue(int expected)
>         {
>             assert(x == expected);
>         }
>
>         void doNothing()
>         {
>         }
>     }
>
>     static void testValueClassArg(Value!Foo foo, int 
> valueToAssert)
>     {
>         foo.assertValue(valueToAssert);
>     }
>
>     {
>         auto foo = createClassValue!Foo(946);
>         assert(foo.x == 946);
>         foo.assertValue(946);
>         testValueClassArg(foo, 946);
>
>         initClassValue(&foo, 391);
>         assert(foo.x == 391);
>         foo.assertValue(391);
>         testValueClassArg(foo, 391);
>     }
>     {
>         auto foo = new Foo(1234);
>         assert(foo.x == 1234);
>         foo.assertValue(1234);
>
>         Value!Foo fooValue = void;
>         copyClassValue(&fooValue, foo);
>         assert(fooValue.x == 1234);
>         fooValue.assertValue(1234);
>         testValueClassArg(fooValue, 1234);
>
>         auto fooValue2 = foo.copyClassValue();
>         assert(fooValue2.x == 1234);
>         fooValue2.assertValue(1234);
>         testValueClassArg(fooValue2, 1234);
>
>         testValueClassArg(foo.copyClassValue(), 1234);
>     }
> }

Strongly reminds me of scoped



More information about the Digitalmars-d mailing list