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.


Reply via email to