On 2014-06-19 4:51 PM, H. S. Teoh via Digitalmars-d wrote:
This assumes that t.init is not a possible valid field value. But in
that case, there's no need to remap it, you just check for t.init
instead. For pointers, where .init is null, this isn't a problem, but
for things like int, where 0 is possible valid value, you may be
accidentally mapping 0 to the default value when the given field
actually exists (and has value 0)!
True, you need to mark failure and drag it to the end. Here's another
try at it:
auto safeDeref(T)(T t, bool failed = false) {
static struct SafeDeref {
T t;
bool fail;
// Make the wrapper as transparent as possible.
alias t this;
auto or(T defVal){
if (fail)
{
return defVal;
}
else
{
return t;
}
}
// This is the magic that makes it all work.
auto opDispatch(string field)()
if (is(typeof(__traits(getMember, t, field))))
{
alias Memb = typeof(__traits(getMember, t, field));
static if (is(typeof(t is null))) {
return safeDeref((t is null) ? Memb.init
: __traits(getMember, t, field), (t is null) ? true
: false);
} else {
return safeDeref(__traits(getMember, t, field),
fail);
}
}
}
return SafeDeref(t, failed);
}