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);
}


Reply via email to