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