Re: Dynamic and Static Casting
On Thu, 10 Feb 2011 11:38:40 -0500, spir wrote: On 02/10/2011 01:38 PM, bearophile wrote: Is a pair of similar staticDownCast(), staticUpCast() fit for Phobos? But I have never needed upcast in D as of now. What are common use cases? Aren't all upcasts static anyways? -Steve
Re: Dynamic and Static Casting
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: pushEAX mov EAX,offset FLAT:_D4test3Bar7__ClassZ mov ECX,offset FLAT:_D4test3Foo7__ClassZ pushEAX pushECX callnear ptr __d_newclass add ESP,4 pushEAX callnear ptr __d_dynamic_cast add ESP,8 pop ECX ret _D4test5test2FZC4test3Bar comdat L0: pushEAX mov EAX,offset FLAT:_D4test3Foo7__ClassZ pushEAX callnear 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
Re: Dynamic and Static Casting
On Thu, 10 Feb 2011 08:02:08 -0500, d coder wrote: Thanks Lars and Bearophile, I will give it a try. I understand that static downcasting is dangerous. But there are places where efficiency is paramount and you are sure that the casting is safe. So I wholeheartedly second your proposal to have the stuff in phobos. Be aware that blindly casting interfaces is not a good idea. An interface pointer is offset into the object and the cast *must* be dynamic. Casting objects from one class to another should be reliable, however. -Steve
Re: Dynamic and Static Casting
Thanks Lars and Bearophile, I will give it a try. I understand that static downcasting is dangerous. But there are places where efficiency is paramount and you are sure that the casting is safe. So I wholeheartedly second your proposal to have the stuff in phobos. Regards - Cherry
Re: Dynamic and Static Casting
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: pushEAX mov EAX,offset FLAT:_D4test3Bar7__ClassZ mov ECX,offset FLAT:_D4test3Foo7__ClassZ pushEAX pushECX callnear ptr __d_newclass add ESP,4 pushEAX callnear ptr __d_dynamic_cast add ESP,8 pop ECX ret _D4test5test2FZC4test3Bar comdat L0: pushEAX mov EAX,offset FLAT:_D4test3Foo7__ClassZ pushEAX callnear ptr __d_newclass add ESP,4 pop ECX ret */ Is a pair of similar staticDownCast(), staticUpCast() fit for Phobos? Bye, bearophile
Re: Dynamic and Static Casting
On Thu, 10 Feb 2011 11:54:02 +, Lars T. Kyllingstad wrote: > On Thu, 10 Feb 2011 16:44:12 +0530, d coder wrote: > >> Greetings All >> >> I have learnt that D has only one casting operator and that is 'cast'. >> The same operator assumes different functionality depending on the >> context in which it he being used. >> >> Now I have a situation where I have to downcast an object and I am sure >> of the objects type and thereby I am sure that the downcast would only >> be successful. To make the operation faster, in C++ I could have used >> static_cast operator, thus giving the RTTI a skip. Would this be >> possible in D? Can I force a static_cast which downcasting? > > Here's one solution. [...] Ok, bearophile's solution is better, because it has fewer casts. 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; } -Lars
Re: Dynamic and Static Casting
d coder: > I have learnt that D has only one casting operator and that is 'cast'. > The same operator assumes different functionality depending on the > context in which it he being used. Walter likes this design, I presume he thinks it's simpler. > Now I have a situation where I have to downcast an object and I am > sure of the objects type and thereby I am sure that the downcast would > only be successful. To make the operation faster, in C++ I could have > used static_cast operator, thus giving the RTTI a skip. Would this be > possible in D? Can I force a static_cast which downcasting? There is no direct support for it because it's considered bad, so this is usually not done in D, it's for special situations only: class Foo {} class Bar : Foo {} Bar test1() { Foo f = new Foo; Bar b = cast(Bar)f; return b; } Bar test2() { Foo f = new Foo; Bar b = cast(Bar)cast(void*)f; return b; } void main() {} DMD 2.051, -O -release -inline: _D4test5test1FZC4test3Bar comdat L0: pushEAX mov EAX,offset FLAT:_D4test3Bar7__ClassZ mov ECX,offset FLAT:_D4test3Foo7__ClassZ pushEAX pushECX callnear ptr __d_newclass add ESP,4 pushEAX callnear ptr __d_dynamic_cast add ESP,8 pop ECX ret _D4test5test2FZC4test3Bar comdat L0: pushEAX mov EAX,offset FLAT:_D4test3Foo7__ClassZ pushEAX callnear ptr __d_newclass add ESP,4 pop ECX ret Bye, bearophile
Re: Dynamic and Static Casting
On Thu, 10 Feb 2011 16:44:12 +0530, d coder wrote: > Greetings All > > I have learnt that D has only one casting operator and that is 'cast'. > The same operator assumes different functionality depending on the > context in which it he being used. > > Now I have a situation where I have to downcast an object and I am sure > of the objects type and thereby I am sure that the downcast would only > be successful. To make the operation faster, in C++ I could have used > static_cast operator, thus giving the RTTI a skip. Would this be > possible in D? Can I force a static_cast which downcasting? Here's one solution. I am not 100% sure of the validity of this, so until someone else vouches for it, it should be considered evil. It works by first casting the reference to a pointer, then to a different pointer type (which goes unchecked), and then to a reference again. // Evil hack to emulate static_cast T staticCast(T, F)(F from) { return cast(T) cast(T*) cast(F*) from; } Example usage: class A { int i; } class B : A { int j; } void main() { auto b = new B; b.i = 123; auto a = staticCast!A(b); assert (a.i == 123); } -Lars
Dynamic and Static Casting
Greetings All I have learnt that D has only one casting operator and that is 'cast'. The same operator assumes different functionality depending on the context in which it he being used. Now I have a situation where I have to downcast an object and I am sure of the objects type and thereby I am sure that the downcast would only be successful. To make the operation faster, in C++ I could have used static_cast operator, thus giving the RTTI a skip. Would this be possible in D? Can I force a static_cast which downcasting? Regards - Cherry