Dynamic and Static Casting

spir denis.spir at gmail.com
Thu Feb 10 08:38:40 PST 2011


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



More information about the Digitalmars-d-learn mailing list