digitalmars.D - rtti cast
- Simon Buerger <krox gmx.net> May 01 2008
- BCS <BCS pathlink.com> May 01 2008
- Simon Buerger <krox gmx.net> May 01 2008
- terranium <spam here.lot> May 02 2008
- Pragma <eric.t.anderton gmail.com> May 02 2008
- terranium <spam here.lot> May 02 2008
- BCS <BCS pathlink.com> May 02 2008
- terranium <spam here.lot> May 07 2008
- BCS <BCS pathlink.com> May 07 2008
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> May 02 2008
- Leandro Lucarella <llucax gmail.com> May 05 2008
- Robert Fraser <fraserofthenight gmail.com> May 02 2008
- downs <default_357-line yahoo.de> May 03 2008
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
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
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 01 2008
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
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
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
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
BCS Wrote: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
In most cases... almost always... When an invalid cast occurs, the error is not in null pointer it's in invalid cast, and replacing InvalidCastException with a hope for NullPointerException is a wrong way.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.
maybe in this case we need some syntax sugar, not a silent cast?
May 07 2008
terranium wrote:BCS Wrote: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
In most cases... almost always... When an invalid cast occurs,
it is not an error. Thinking about it, I can't recall ever casting to a derived type where a failed cast was an indication of a bug. In the few times I have done it, it has always been in the context of "if a is'a B then" (and not just in the code but in the proper function of the program as well).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.
maybe in this case we need some syntax sugar, not a silent cast?
a little sugar for the other way might be even handier // not tested template Force_Cast(T) { T Force_Cast(U)(U u) { static assert(is(U : T), "cant cast from " ~ U.stringof ~ " to " ~ T.stringof); if(auto t = cast(T)u) return t; else throw new InvalidCastException("failed cast from " ~ U.stringof ~ " to " ~ T.stringof); } }
May 07 2008
"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
Jarrett Billingsley, el 2 de mayo a las 16:40 me escribiste: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.
C++ have the 2 too. If you cast a pointer, it returns NULL if the cast fails but if you cast a reference, the cast throws a bad_cast exception if it fails. Unfortunatelly this can't be done in D (at least in an elegant way) because it's reference semantics for objects. But I thinks std.contracts.enforce[1] is a perfect solution for this: auto y = enforce(cast(D)x); // y is not null from here on Or just use assert if you want the check to be gone in release builds: auto y = cast(D)x; assert(y !is null); [1] http://www.digitalmars.com/d/2.0/phobos/std_contracts.html -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- The number of wars fought between countries That both have at least one McDonalds is zero
May 05 2008
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 02 2008
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
May 03 2008









BCS <BCS pathlink.com> 