Templates: generic "return null;"

TheFlyingFiddle theflyingfiddle at gmail.com
Mon Feb 3 16:43:52 PST 2014


On Monday, 3 February 2014 at 10:25:19 UTC, Chris wrote:
> Is there a way I can make the return type in getAttribute 
> generic? null does not work with numbers.
>
> MyStruct(T) {
>   T[T] attributes;
>   // ....
>   public auto getAttribute(T attr) {
>       if (!(attr in attributes)) {
>         return null; // Doesn't work for numbers!
>       }
>       return attributes[attr];
>     }
> }
>
> void main() {
>   auto myStr = MyStruct!int(0); // Error
> }

Whenever i am faced with this situation i do one (or more then 
one) of the following things.

struct MyStruct(T)
{
     T[T] attributes;

    //(1) Forward the underlying access method Eg:
    auto opBinaryRight(string s : "in")(T attrib)
    {
       return attrib in attributes;
    }

    //(2) make a try method.
    bool tryAttrib(T attrib, out T outAttrib)
    {
        auto p = attrib in attributes;
        if(p) outAttrib = *p;
        return p !is null;
    }



    //(3) Give user option to set default value.
    T attribOrDefault(T attrib, T default)
    {
        auto p = attrib im attributes;
        return p is null ? default : attrib;
    }


    //(4) Use Nullable!T (I prefer #5 over this one)
    Nullable!T attribOrNull(T attrib)
    {
        Nullable!T result;
        auto p = attrib ib attributes;
        if(p) result = *p;
        return result;
    }

    //(5) Use a pointer but not forward in operator.
    T* attribPtr(T attrib)
    {
       return attrib in attributes;
    }

    //(6) Throw exception (I only do this in combination with one 
of the above)
    T attribEx(T attrib)
    {
      return *enforce!AttribNotFoundEx(attrib in attributes);
    }
}

My personal preference using #2 and #3 in combination. #2 covers 
the basic case "Is this thing avalible?" and #3 covers the case 
"Give it to me if it is avalible or use this default value" I 
think it gives a clear image of what your code is doing at the 
callsite. Only using #2 or #3 limits you in this sence.

For #1, #4 and #5 i personally stay away from them. They force 
the caller to either use an if or potentially trigger a null 
pointer derecerence. (Btw what is the benefit of #4? I have never 
used it since it seems pointless)

I very rarly use attribEx. I don't think code shuld just spew 
exceptions all over the place. They should be reserved for really 
bad stuff, like bounds checks. One exception i make to this rule 
is if i'm dealing with ranges. Since the other methods don't lend 
themselfs for UFCS-chaing.




More information about the Digitalmars-d-learn mailing list