Re: Dynamic and Static Casting

2011-02-10 Thread Steven Schveighoffer

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

2011-02-10 Thread spir

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

2011-02-10 Thread Steven Schveighoffer

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

2011-02-10 Thread d coder
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

2011-02-10 Thread bearophile
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

2011-02-10 Thread Lars T. Kyllingstad
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

2011-02-10 Thread bearophile
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

2011-02-10 Thread Lars T. Kyllingstad
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

2011-02-10 Thread d coder
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