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