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