On 02/10/2011 01:38 PM, bearophile wrote:
Lars T. Kyllingstad:

Ok, bearophile's solution is better, because it has fewer casts.

And your solution was better because it's inside a function :-)


I forgot you can cast to void*.  So here's an improved version, with some
template constraints to make sure it's only used for class types:

     T staticCast(T, U)(U obj)  if (is(T == class)&&  is(U == class))
     {
         return cast(T) cast(void*) obj;
     }


And what about:

import std.stdio, std.traits, std.typetuple;

/// C++ static_cast for just down-casting
T staticDownCast(T, F)(F from) if (is(F == class)&&
                                    is(T == class)&&
                                    staticIndexOf!(F, BaseClassesTuple!T) != -1)
     in {
         assert((from is null) || cast(T)from !is null);
     } body {
         return cast(T)cast(void*)from;
     }

class Foo {}
class Bar : Foo {}
class Spam {}

Bar test1() {
     Foo f = new Foo;
     Bar b = cast(Bar)f;
     return b;
}

Bar test2() {
     Foo f = new Foo;
     Bar b = staticDownCast!Bar(f);
     return b;
}

void main() {
     Spam s = new Spam;
     Bar b = staticDownCast!Bar(s); // error
}

/*
_D4test5test1FZC4test3Bar   comdat
L0:     push    EAX
         mov EAX,offset FLAT:_D4test3Bar7__ClassZ
         mov ECX,offset FLAT:_D4test3Foo7__ClassZ
         push    EAX
         push    ECX
         call    near ptr __d_newclass
         add ESP,4
         push    EAX
         call    near ptr __d_dynamic_cast
         add ESP,8
         pop ECX
         ret

_D4test5test2FZC4test3Bar   comdat
L0:     push    EAX
         mov EAX,offset FLAT:_D4test3Foo7__ClassZ
         push    EAX
         call    near ptr __d_newclass
         add ESP,4
         pop ECX
         ret
*/


Is a pair of similar staticDownCast(), staticUpCast() fit for Phobos?

I think so. Definitely need staticDownCast very often for all functionality in type-hierarchy-generic code where some arguments are known to be of a given subtype. Typically, some func produces a collection of a given supertype (say, Node). It may be stored on a member, or produced on need. Some other func takes such a collection as input; but using this func means we know all or some of the objects are of a given subtype (say AssignmentNode); and indeed, we need the additional members of the subtype. Other case, each Node holds one or more other nodes. In the general case, they can be of any subtype. But when a func takes an AssignmentNode, then it knows its subnodes must be NameNode and ExpressionNode, hey!, ain't it clever? And indeed it'll need to access members specific to their subtypes.

But I have never needed upcast in D as of now. What are common use cases?

Denis
--
_________________
vita es estrany
spir.wikidot.com

Reply via email to