View mode: basic / threaded / horizontal-split · Log in · Help
May 01, 2008
rtti cast
hi
I would like to do some RTTI, but not with type-IDs, but in some more 
pretty way. I'll simply post some code to show you what I mean :) . My 
Question is now: Does anyone know, how to do sth alike with the 
current D implementation (maybe with templates, but I dont see a nice 
way) ? Or do you think it could be worth an extension for D 2.0 ?
Krox

Code:

class Base {}
class A : Base
{
	void function_A() { ... }
}
class B : Base {}
{
	void function_B() { ... }
}

void main()
{
	Base x = ...
	
	// checks if x is of type A, and if so, declares y as A alias of x 
with other type
	if (x == A y)	
		y.function_A();
	else if(x == B y)
		y.function_B();
}
May 01, 2008
Re: rtti cast
Simon Buerger wrote:
> hi
> I would like to do some RTTI, but not with type-IDs, but in some more 
> pretty way. I'll simply post some code to show you what I mean :) . My 
> Question is now: Does anyone know, how to do sth alike with the current 
> D implementation (maybe with templates, but I dont see a nice way) ? Or 
> do you think it could be worth an extension for D 2.0 ?
> Krox
> 
> Code:
> 
> class Base {}
> class A : Base
> {
>     void function_A() { ... }
> }
> class B : Base {}
> {
>     void function_B() { ... }
> }
> 
> void main()
> {
>     Base x = ...
>     
>     // checks if x is of type A, and if so, declares y as A alias of x 
> with other type
>     if (x == A y)   
>         y.function_A();
>     else if(x == B y)
>         y.function_B();
> }

this work?

if (auto y = cast(A)x)
	y.function_A();
else if(auto y = cast(B)x)
	y.function_B();
May 01, 2008
Re: rtti cast
BCS wrote:
> this work?
> 
> if (auto y = cast(A)x)
>     y.function_A();
> else if(auto y = cast(B)x)
>     y.function_B();
> 

Well, honestly I'm really impressed. Thats perfectly what I wanted. 
Seems to be standard, but I didn't knew about it *lolz*. Okay, seems 
to be solved then. Thanks.
May 02, 2008
Re: rtti cast
Simon Buerger Wrote:

> BCS wrote:
> > this work?
> > 
> > if (auto y = cast(A)x)
> >     y.function_A();
> > else if(auto y = cast(B)x)
> >     y.function_B();
> > 
> 
> Well, honestly I'm really impressed. Thats perfectly what I wanted. 
> Seems to be standard, but I didn't knew about it *lolz*. Okay, seems 
> to be solved then. Thanks.

OMG invalid cast doesn't throw exception????
May 02, 2008
Re: rtti cast
terranium Wrote:

> Simon Buerger Wrote:
> 
> > BCS wrote:
> > > this work?
> > > 
> > > if (auto y = cast(A)x)
> > >     y.function_A();
> > > else if(auto y = cast(B)x)
> > >     y.function_B();
> > > 
> > 
> > Well, honestly I'm really impressed. Thats perfectly what I wanted. 
> > Seems to be standard, but I didn't knew about it *lolz*. Okay, seems 
> > to be solved then. Thanks.
> 
> OMG invalid cast doesn't throw exception????

Nope.  Invalid casts simply return null.  If you absolutely need an exception, then you can just wrap the cast in a templated function:

class DynamicCastException : Exception{
	public this(char[] reason){
		super(reason);
	}
}

T dyn_cast(T)(Object x){
   T result = cast(T)x;
   if(result is null) throw new DynamicCastException("Cannot cast to type " ~ T.stringof);
   return result;
}

class A{}

class B:A{}

class C{}

void main(){
	B x = new B();
	C y = dyn_cast!(C)(x);
}
May 02, 2008
Re: rtti cast
Pragma Wrote:

> If you absolutely need an exception

And who don't? Yet another D misdesign to be worked around? And where will be more legacy design typos in the end? In C++ or in D?
May 02, 2008
Re: rtti cast
terranium wrote:
> Pragma Wrote:
> 
> 
>>If you absolutely need an exception
> 
> 
> And who don't? Yet another D misdesign to be worked around? 
> And where will be more legacy design typos in the end? In
> C++ or in D?

In most cases forgetting to check the cast return will result in an 
seg-v from a dereferenced null because you almost always use it as the 
very next thing. Also it will never result in a miss use for the same 
reason, the pointer doesn't point to anything.

Having the "bad cast" -> null is very handy when you don't known if the 
cast will be good. It mean you can test it without invoking the 
exception system and all the overhead that entails.
May 02, 2008
Re: rtti cast
"terranium" <spam@here.lot> wrote in message 
news:fvf93j$194u$1@digitalmars.com...
> Pragma Wrote:
>
>> If you absolutely need an exception
>
> And who don't?

I don't.

I perform downcasts extremely rarely.  When I do, it's usually in code like:

if(auto y = cast(Y)x)
   ...
else
   // not a Y, try something else

That is, the code is only executed if the cast succeeds.

Furthermore, it's a lot easier and more efficient to have the cast return 
null and throw an exception _only if needed_ than to throw an exception and 
then have to catch it:

try
{
   auto y = cast(Y)x;
   ...
}
catch(CastException e)
{
   // not a Y, try something else..
}

For that matter, some languages (like C#) have both kinds of casts - one 
that throws an exception and one that doesn't.  Either can really be 
implemented in the other, but the null-returning kind is more basic and 
efficient.
May 02, 2008
Re: rtti cast
terranium wrote:
> Pragma Wrote:
> 
>> If you absolutely need an exception
> 
> And who don't? Yet another D misdesign to be worked around? And where will be more legacy design typos in the end? In C++ or in D?

In Java, I often find myself writing code like:

void process(Object o)
{
    if(o instanceof String)
    {
        String s = (String) o;
        // ...
    }
    else if(o instanceof List)
    {
        List<String> l = (List<String>) o;
        // ...
    }
}

It's much easier (and more efficient) to use the D way:

void process(Object o)
{
    if(auto s = cast(string) o)
    {
        //...
    }
    else if(auto l = cast(Seq!(string) o)
    {
        // ...
    }
}
May 04, 2008
Re: rtti cast
terranium wrote:
> Pragma Wrote:
> 
>> If you absolutely need an exception
> 
> And who don't? Yet another D misdesign to be worked around? And where will be more legacy design typos in the end? In C++ or in D?

Actually, since you don't know if the cast is really valid, it failing is a regular outcome.

As such, an exception (which is reserved, appropriately, for *exceptional* events), is totally the wrong approach to use.

Note that with the current behavior, you can incur the runtime speed loss of throwing an exception if you _want_ to, by using the above templated wrapper, but if throwing an exception were the only possibility, you couldn't possibly get that speed back.

So it really is better this way. :)

--downs
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home