casts / wildcards for parametrized types

tx tx at lowtech-labs.org
Thu Aug 1 17:40:43 PDT 2013


Thanks for the reply Ali. Everything you wrote makes sense, but I
think I may have oversimplified the problem in my original email. In
general I don't care about what T is when working with Box (or
ConcreteBox as it were), but I do care that Box contains a T. Consider
this rather contrived example (I'm aware that it's a poorly written
function, it just captures my issue.):

bool truthy(Item a, Item b){
  if(cast(LongBox) a && cast(LongBox) b){
    return (cast(LongBox) a).value && (cast(LongBox) a).value;
  } else if(cast(CharBox) a && cast(CharBox) b){
    return (cast(CharBox) a).value && (cast(CharBox) a).value;
  } else {
    return !(a is null || b is null);
  }
}

I would much rather write something like:

bool truthy(Item a, Item b){
  if(cast(Box) a && cast(Box) b){
    return (cast(Box) a).value && (cast(Box) a).value;
  } else {
    return !(a is null || b is null);
  }
}

To be more explicit: By the time I'm writing these if-else/cast
statements I already know that my objects are both instances of some
type of Box and I also know that the operation(s) I plan to perform on
them are valid for any T that box can contain.

-tx

--
tx.lowtech-labs.org / tx at lowtech-labs.org


On Thu, Aug 1, 2013 at 5:06 PM, Ali Çehreli <acehreli at yahoo.com> wrote:
> On 08/01/2013 04:28 PM, tx wrote:
>
>> Hi All,
>> Hoping somebody can provide some help here, I have a set of classes
>> that are similar to the following
>>
>> class Item{}
>>
>> class Box(T) : Item {
>>    T value;
>>    //  ...
>> }
>>
>> //Along with some aliases:
>>
>> alias Box!(long) LongBox;
>> alias Box!(char) CharBox;
>> //etc.
>>
>>
>>
>> I'd like to have a function that operates on instances of Item, but I
>> want to specialize the behavior to handle instances of Box
>> differently. Is there anyway I can upcast Item to Box without
>> specifying the type parameter? In my case I don't really care about
>> what T is, just that I'm working with a Box of something. Currently I
>> have a whole if-else ladder checking to see if I'm working with an
>> instance of each of the aliases and casting appropriately, but I would
>> prefer to just write that once. I guess I'm looking for something like
>> cast(Box). Is this possible?
>>
>> To put it another way, is there a D equivalent to the Java syntax of
>> Box<?>
>
> Inserting another layer to the hierarchy is a solution. ConcreteBox is the
> same as your Box and the new Box in a non-template intermediate class:
>
> class Item{}
>
> class Box : Item{}
>
> class ConcreteBox(T) : Box {
>   T value;
>   //  ...
> }
>
> alias ConcreteBox!(long) LongBox;
> alias ConcreteBox!(char) CharBox;
> //etc.
>
> // Explicit check
> int foo(Item item)
> {
>     if (cast(Box)item) {
>         return 1;
>     }
>
>     return 0;
> }
>
> unittest
> {
>     assert(foo(new Item()) == 0);
>     assert(foo(new LongBox()) == 1);
>     assert(foo(new CharBox()) == 1);
> }
>
> // Automatic dispatch for compile-time binding
> class Foo
> {
>     int foo(Item item)
>     {
>         return 0;
>     }
>
>     int foo(Box box)
>     {
>         return 1;
>     }
> }
>
> unittest
> {
>     auto f = new Foo();
>     assert(f.foo(new Item()) == 0);
>     assert(f.foo(new LongBox()) == 1);
>     assert(foo(new CharBox()) == 1);
> }
>
> void main()
> {}
>
> Ali
>


More information about the Digitalmars-d-learn mailing list