digitalmars.D - rtti cast
- Simon Buerger (28/28) May 01 2008 hi
- BCS (6/37) May 01 2008 this work?
- Simon Buerger (4/11) May 01 2008 Well, honestly I'm really impressed. Thats perfectly what I wanted.
- terranium (2/14) May 02 2008 OMG invalid cast doesn't throw exception????
- Pragma (19/35) May 02 2008 Nope. Invalid casts simply return null. If you absolutely need an exce...
- terranium (2/3) May 02 2008 And who don't? Yet another D misdesign to be worked around? And where wi...
- BCS (8/17) May 02 2008 In most cases forgetting to check the cast return will result in an
- terranium (3/8) May 07 2008 maybe in this case we need some syntax sugar, not a silent cast?
- BCS (22/36) May 07 2008 it is not an error.
- Jarrett Billingsley (25/28) May 02 2008 I don't.
- Leandro Lucarella (20/24) May 05 2008 C++ have the 2 too. If you cast a pointer, it returns NULL if the cast
- Robert Fraser (27/32) May 02 2008 In Java, I often find myself writing code like:
- downs (6/11) May 03 2008 Actually, since you don't know if the cast is really valid, it failing i...
- terranium (5/18) May 07 2008 yeah, try something else, hide the bug :)
- BCS (7/37) May 07 2008 That's not a bug. That is the normal idiom for checking to see if x is a...
- BCS (1/3) May 07 2008
- Jarrett Billingsley (7/12) May 07 2008 I _really_ don't understand where you're coming from here. I'd be
- terranium (2/4) May 07 2008 In any language I often find myself thinking about program's desing.
- terranium (3/7) May 07 2008 You'll get that speed back without hours spent in debugger trying to fig...
- BCS (12/20) May 07 2008 The point is that offtent a failed cast is not an indecation of an
- terranium (3/6) May 08 2008 making default behavior unsafe is a wrong way.
- BCS (6/15) May 08 2008 Ok, some some people use then one way, I use them another. That doesn't ...
- terranium (3/11) May 08 2008 The program will not stop in a predictable manner since a third party li...
- Simen Kjaeraas (6/11) May 08 2008 So, don't send any unsanitized data to a third-party library? A third-pa...
- terranium (2/5) May 08 2008 cast is not a typecheck, it's a type conversion.
- Janice Caron (18/19) May 08 2008 In C++, there is a difference between a regular cast and a
- terranium (2/5) May 08 2008 Typecheck just determines whether an object can be cast to the target ty...
- terranium (2/15) May 08 2008 I see polimorphism should help here.
- BCS (17/33) May 08 2008 dosn't always work
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:OMG invalid cast doesn't throw exception????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
terranium Wrote:Simon Buerger Wrote: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); }BCS wrote:OMG invalid cast doesn't throw exception????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
Pragma Wrote:If you absolutely need an exceptionAnd 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: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.If you absolutely need an exceptionAnd 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
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 theIn 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: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).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 theIn most cases... almost always... When an invalid cast occurs,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); } }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" <spam here.lot> wrote in message news:fvf93j$194u$1 digitalmars.com...Pragma Wrote: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.. } 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.If you absolutely need an exceptionAnd who don't?
May 02 2008
Jarrett Billingsley, el 2 de mayo a las 16:40 me escribiste: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: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) { // ... } }If you absolutely need an exceptionAnd 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: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. :) --downsIf you absolutely need an exceptionAnd 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 03 2008
Jarrett Billingsley Wrote:I perform downcasts extremely rarely.That's *exactly* why you need safe cast.if(auto y = cast(Y)x) ... else // not a Y, try something elseyeah, try something else, hide the bug :)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:most programmers won't bother to thow an exception in this case, they just cast and go.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....efficient bugmaker.
May 07 2008
terranium wrote:Jarrett Billingsley Wrote:How does that follow? I don't see the connection.I perform downcasts extremely rarely.That's *exactly* why you need safe cast.That's not a bug. That is the normal idiom for checking to see if x is a Y and acting on it.if(auto y = cast(Y)x) ... else // not a Y, try something elseyeah, try something else, hide the bug :)And this will result in a Seg-V. The program will stop in a predictable manner. IMHO (and it seems others opinions) that is what matters.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:most programmers won't bother to thow an exception in this case, they just cast and go.the same can be said going the other way. IMHO any code that take athat 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....efficient bugmaker.
May 07 2008
the same can be said going the other way.dang non-linear editing (scratch the following):IMHO any code that take a
May 07 2008
"terranium" <spam here.lot> wrote in message news:fvs67v$1gge$1 digitalmars.com...That's *exactly* why you need safe cast. ... yeah, try something else, hide the bug :) ... ...efficient bugmaker.I _really_ don't understand where you're coming from here. I'd be interested to see some example of code where an invalid downcast were a bug and where a failed cast _should_ throw an exception. I've only ever used downcasts in D as a replacement for Java's "instanceof", where it's just a simple typecheck.
May 07 2008
Jarrett Billingsley Wrote:void GetNodes() { auto obj = Parser.GetNextObject(); MyList.Add(cast(INode)obj); }yeah, try something else, hide the bug :) ... ...efficient bugmaker.I _really_ don't understand where you're coming from here. I'd be interested to see some example of code where an invalid downcast were a bug and where a failed cast _should_ throw an exception. I've only ever used downcasts in D as a replacement for Java's "instanceof", where it's just a simple typecheck.
May 08 2008
Reply to terranium,Jarrett Billingsley Wrote:Dang, you just reminded me that I do have some code that downcasts and expects stuff to work (it check the cast though). It's in a generated parser I'm working on.void GetNodes() { auto obj = Parser.GetNextObject(); MyList.Add(cast(INode)obj); }yeah, try something else, hide the bug :) ... ...efficient bugmaker.I _really_ don't understand where you're coming from here. I'd be interested to see some example of code where an invalid downcast were a bug and where a failed cast _should_ throw an exception. I've only ever used downcasts in D as a replacement for Java's "instanceof", where it's just a simple typecheck.
May 08 2008
Robert Fraser Wrote:In Java, I often find myself writing code like:In any language I often find myself thinking about program's desing.
May 07 2008
downs Wrote:As such, an exception (which is reserved, appropriately, for *exceptional* events), is totally the wrong approach to use.Yes, function received wrong input, this is normal, if we want, we throw exception, if we want, we ignore it.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.You'll get that speed back without hours spent in debugger trying to figure out, "where this null came from"?
May 07 2008
terranium wrote:downs Wrote:The point is that offtent a failed cast is not an indecation of an error. For instance code like this class A {} class B1 : A {} class B2 : A {} void foo(A a) { if(auto b = cast(B1)a) {} else if(auto b = cast(B2)a) {} else {} }As such, an exception (which is reserved, appropriately, for *exceptional* events), is totally the wrong approach to use.Yes, function received wrong input, this is normal, if we want, we throw exception, if we want, we ignore it.
May 07 2008
BCS Wrote:Thinking about it, I can't recall ever casting to a derived type where a failed cast was an indication of a bug.You can't, others can. When a function receives unexpected input it's a bug.a little sugar for the other way might be even handiermaking default behavior unsafe is a wrong way.
May 08 2008
Reply to terranium,BCS Wrote:Ok, some some people use then one way, I use them another. That doesn't prove that they your proposal is better (or worse) than the current way.Thinking about it, I can't recall ever casting to a derived type where a failed cast was an indication of a bug.You can't, others can.When a function receives unexpected input it's a bug.That's irrelevant. What I'm saying is that in every case I know of where I have used such a cast, the cast failing was /not/ unexpected. It was mealy a legitimate and /expected/ "no" answer to the question "is a's type B?"
May 08 2008
BCS Wrote:When you do some unusual thing, the probability of mistake increases.How does that follow? I don't see the connection.I perform downcasts extremely rarely.That's *exactly* why you need safe cast.And this will result in a Seg-V. The program will stop in a predictable manner. IMHO (and it seems others opinions) that is what matters.The program will not stop in a predictable manner since a third party library can silently handle nulls, e.g. XML serialization. And if it stops in an AV this happens in an unpredictable location - miles away from the place where the bug was triggered. What matters is a presence of bugs, to solve this you must eliminate them, to eliminate them you should know, where the bug was triggered (and of course you need to know that there is a bug), to help locating bug an exception should be thrown as soon as possible after the bug was triggered, ideally exception should be thrown in the same location, where the bug was triggered.
May 08 2008
terranium <spam here.lot> wrote:BCS Wrote:So, don't send any unsanitized data to a third-party library? A third-party library might also catch and ignore exceptions, if the language automatically threw one when seeing an invalid cast. -- SimenAnd this will result in a Seg-V. The program will stop in a predictable manner. IMHO (and it seems others opinions) that is what matters.The program will not stop in a predictable manner since a third party library can silently handle nulls, e.g. XML serialization.
May 08 2008
Jarrett Billingsley Wrote:I've only ever used downcasts in D as a replacement for Java's "instanceof", where it's just a simple typecheck.cast is not a typecheck, it's a type conversion.
May 08 2008
2008/5/8 terranium <spam here.lot>:cast is not a typecheck, it's a type conversion.In C++, there is a difference between a regular cast and a dynamic_cast. The expression dynamic_cast<T>(x) performs a run-time type check and type conversion. See http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/topic/com.ibm.vacpp6m.doc/language/ref/clrc05keyword_dynamic_cast.htm dynamic_cast<T>() returns a null pointer of type T if the cast fails. Users of dynamic_cast<T>() are therefore required always to check the return value for null. This is not an indication of a bug - it is designed behavior. Thus, in C++ (1) traditional cast is not a typecheck, it's a type conversion (2) dynamic cast is a a runtime type check Unfortunately, D's cast(T)x behaves exactly like C++'s dynamic_cast<T>(x) when it comes to casting up and down a class heirarchy. D only has one kind of cast, and it does both jobs. So Jarrett is using D's casts correctly, /but/ D's casts are themselves flawed. The "one cast that does everything" ideology is just a tool for making bugs.
May 08 2008
Janice Caron Wrote:(1) traditional cast is not a typecheck, it's a type conversion (2) dynamic cast is a a runtime type checkTypecheck just determines whether an object can be cast to the target type, so does a type conversion and applies a typecheck during the conversion and the result depends on whether the typecheck succeeded. It was noted that for failed typecheck for pointer type null is returned and for failed typecheck for reference type bad_cast is thrown. And D reference types are very similar to those of C++ (at least in syntax :) ) except that C++ reference can't be changed after initialization.
May 08 2008
BCS Wrote:The point is that offtent a failed cast is not an indecation of an error. For instance code like this class A {} class B1 : A {} class B2 : A {} void foo(A a) { if(auto b = cast(B1)a) {} else if(auto b = cast(B2)a) {} else {} }I see polimorphism should help here.
May 08 2008
Reply to terranium,BCS Wrote:dosn't always work module third.party.lib; class A {} module my.lib.one class B1 : A { int newFn(){...}} module my.lib.teo class B2 : A { char somthingNew(char[] c){...}} void foo(A a) { if(auto b = cast(B1)a) b.newFn(); else if(auto b = cast(B2)a) b.somthingNew("hello"); else throw new Error("a isn't a B1 or B2"); }The point is that offtent a failed cast is not an indecation of an error. For instance code like this class A {} class B1 : A {} class B2 : A {} void foo(A a) { if(auto b = cast(B1)a) {} else if(auto b = cast(B2)a) {} else {} }I see polimorphism should help here.
May 08 2008