Generic Property Implementation

Simen Kjærås simen.kjaras at gmail.com
Tue Feb 20 15:34:46 UTC 2018


On Tuesday, 20 February 2018 at 14:34:53 UTC, bauss wrote:
> Would there be a reason why this wouldn't be a good 
> implementation?

What is the intended use case for this? The main feature seems to 
be an ability to have read-only members, which is nice. Are there 
other benefits?


> If so what and how could it be improved?
> 
> Are there flaws in an implementation like this?

[snip]

>     bool opEquals(T other)

Why not use the default == implementation? It's supposed to do 
the right thing. Yours will fail for structs and classes. Since 
you're using alias this, it shouldn't even be necessary to 
implement opEquals - the right one should be called automagically.


>     static if (!(isArray!T) && !(isAssociativeArray!T))
>     {
>         int opCmp(T other)

This will give unexpected errors when comparing structs or 
classes that don't overload opCmp. Better to replace the static 
if with is(typeof(T.init < T.init)), or better yet, 
std.traits.isOrderingComparable.

Also, it's not necessary - alias this ensures that the correct 
opCmp function is called.


>     string toString()

Why not use std.typecons.to for everything in here? Its 
implementors probably have thought of many more corner cases than 
you have. There is an argument to be made for compile-time 
overhead, I guess.


So, my version of the same:

struct Property(T, bool readOnly = false)
{
     private T _value;

     static if (readOnly)
             T __GET() { return _value; }
     else
         ref T __GET() { return _value; }

     alias __GET this;

     string toString()
     {
         import std.conv : to;
         return _value.to!string;
     }
}

One more thing: while you provided some very nice examples of how 
to use the type, it would be nice to have these more test-like. 
Something like this:

unittest
{
     auto foo = new Foo;
     foo.baz = "Hello";

     // Check that value was set correctly:
     assert(foo.baz == "Hello");

     // You can even check if something will compile:
     assert(!__traits(compiles, foo.bar = 24));
}

Sorry if this came off a bit crass - I don't understand when I 
should use it, so it's hard to give feedback on that.

--
   Simen


More information about the Digitalmars-d-learn mailing list