Jump to page: 1 24  
Page
Thread overview
casts
Nov 23, 2001
Pavel Minayev
Nov 23, 2001
Walter
Nov 24, 2001
Pavel Minayev
Nov 24, 2001
Walter
Nov 24, 2001
Russell Borogove
Nov 24, 2001
Pavel Minayev
Nov 24, 2001
Russell Borogove
Nov 24, 2001
Pavel Minayev
Nov 24, 2001
Russell Borogove
Nov 25, 2001
Pavel Minayev
Nov 25, 2001
Walter
Nov 29, 2001
Sean L. Palmer
Nov 29, 2001
Sean L. Palmer
Nov 30, 2001
a
Nov 30, 2001
Russell Borogove
Nov 30, 2001
a
Nov 30, 2001
Russ Lewis
Nov 30, 2001
a
Nov 30, 2001
Russ Lewis
Dec 01, 2001
a
Dec 01, 2001
Russ Lewis
Dec 01, 2001
a
Dec 01, 2001
Russ Lewis
Dec 02, 2001
a
Dec 03, 2001
Russ Lewis
Dec 01, 2001
Russ Lewis
Re: switch
Dec 02, 2001
Sean L. Palmer
Dec 03, 2001
a
Dec 03, 2001
Sean L. Palmer
Dec 03, 2001
Pavel Minayev
Dec 05, 2001
Walter
Dec 05, 2001
Russell Borogove
Dec 05, 2001
Pavel Minayev
Dec 05, 2001
Russell Borogove
Dec 05, 2001
Pavel Minayev
Dec 06, 2001
Sean L. Palmer
Dec 11, 2001
Walter
Dec 02, 2001
Sean L. Palmer
Dec 02, 2001
Pavel Minayev
Nov 30, 2001
Russ Lewis
November 23, 2001
The specification says that all casts of objects are
done with run-time checking - and that's good - and
if the type doesn't match, null is returned! I don't
think it's a good idea, since you could make a cast
in one place of the program, and any error would get
unnoticed, and then try to use the null-pointer in
other place somewhere hundred lines after... could
be VERY hard to find the actual reason of crash. Maybe
it's better to throw an exception on bad cast - like
it's done in C++ (and in Delphi by the way).

On other hand, we need an "is" or "instanceof" operator then...


November 23, 2001
But all the "is" operator would do is check the cast for a null return.  It seems redundant.

"Pavel Minayev" <evilone@omen.ru> wrote in message news:9tmb6p$2snv$1@digitaldaemon.com...
> The specification says that all casts of objects are
> done with run-time checking - and that's good - and
> if the type doesn't match, null is returned! I don't
> think it's a good idea, since you could make a cast
> in one place of the program, and any error would get
> unnoticed, and then try to use the null-pointer in
> other place somewhere hundred lines after... could
> be VERY hard to find the actual reason of crash. Maybe
> it's better to throw an exception on bad cast - like
> it's done in C++ (and in Delphi by the way).
>
> On other hand, we need an "is" or "instanceof" operator then...
>
>


November 24, 2001
"Walter" <walter@digitalmars.com> wrote in message news:9tmi2t$31hm$1@digitaldaemon.com...

> But all the "is" operator would do is check the cast for a null return.
It
> seems redundant.

No. My proposal is to throw an exception on bad cast
rather than return null, to prevent further errors.


November 24, 2001
ok, I understand.

"Pavel Minayev" <evilone@omen.ru> wrote in message news:9tni37$ir0$1@digitaldaemon.com...
>
> "Walter" <walter@digitalmars.com> wrote in message news:9tmi2t$31hm$1@digitaldaemon.com...
>
> > But all the "is" operator would do is check the cast for a null return.
> It
> > seems redundant.
>
> No. My proposal is to throw an exception on bad cast
> rather than return null, to prevent further errors.
>
>


November 24, 2001
Pavel Minayev wrote:

> "Walter" <walter@digitalmars.com> wrote in message
> news:9tmi2t$31hm$1@digitaldaemon.com...
> 
> 
>>But all the "is" operator would do is check the cast for a null return.
>>
> It
> 
>>seems redundant.
>>
> 
> No. My proposal is to throw an exception on bad cast
> rather than return null, to prevent further errors.



Whether we have casts return null or throw exception, it's possible
to wrap the language's standard cast in order to simulate the other
behavior. Considered from that point, it's (a) slightly easier to
have the standard cast return null and write a wrapper that throws
than vice versa[1], and (b) faster in run-time to return null than to
throw an exception.

The same argument can be made regarding memory allocation[2], of
course, or file I/O, and then we're back to testing the return
value from every function.[3]

So it really comes down to whether or not you consider throwing a
bunch of objects which have "void in common" into the same container
to be good programming practice, or no.

-RB


[1] Two ways come to mind: "if (obj == null) throw" or "obj->Method()".

[2] Which is why my memory manager offers an interface which includes
a "this allocation is non-critical, so don't work too hard, and return
NULL if you have to" flag as an option.
[3] ...the way god intended you to write code.


November 24, 2001
"Russell Borogove" <kaleja@estarcion.com> wrote in message news:3BFF539D.40808@estarcion.com...

> Whether we have casts return null or throw exception, it's possible to wrap the language's standard cast in order to simulate the other behavior. Considered from that point, it's (a) slightly easier to have the standard cast return null and write a wrapper that throws than vice versa[1], and (b) faster in run-time to return null than to throw an exception.

The problem is somewhat different. In general, I suppose that an object
to be casted should always conform to the new type, for classes at least -
what are you going to do with a wrongly-casted pointer anyhow? So
it is a deliberate error, and is supposed to never occur in a final
version of the program (dreams...). So in most cases you don't in fact
write any checking code, you just rely on it always working properly.
And when debugging the program, if the cast is wrong, you'd most likely
want to know about it - and you will if it throws an exception. On other
hand, null pointer is just silently accepted and at some later point
you get an access violation. If you do the cast in a function call, and
the function transfers it further... you could end with an exception
in some completely different module (long, long ago in a function far,
far away =)) staring on the screen and thinking, "WHAT the hell can be
wrong with this???" - well you might know the feeling....

Or maybe introduce two cast keywords - one for safe and one for unsafe cast? Pascal syntax, maybe? LOL



November 24, 2001
Pavel Minayev wrote:

> "Russell Borogove" <kaleja@estarcion.com> wrote in message
> news:3BFF539D.40808@estarcion.com...
> 
> 
>>Whether we have casts return null or throw exception, it's possible
>>to wrap the language's standard cast in order to simulate the other
>>behavior. Considered from that point, it's (a) slightly easier to
>>have the standard cast return null and write a wrapper that throws
>>than vice versa[1], and (b) faster in run-time to return null than to
>>throw an exception.
>>
> 
> The problem is somewhat different. In general, I suppose that an object
> to be casted should always conform to the new type, for classes at least -
> what are you going to do with a wrongly-casted pointer anyhow? So
> it is a deliberate error, and is supposed to never occur in a final
> version of the program (dreams...).


I do understand your point, but some people design their code differently.

It may or may not be an error. Say we're talking about game code, and you're iterating over a collection of objects derived from class Entity, checking to see if they're castable to class ThinkingEntity, and if so, calling their Think() method. There are any number of good reasons to maintain all your entities in a single collection even though they're
not completely compatible in some contexts. The alternative is to bloat the base class with a bunch of virtual functions which will be no-op in the majority of cases. (Not to mention that sometimes you won't be allowed to mess with the base class.)

My point is that from a single cast-else-null primitive, you can build cast-else-throw and and is-safe-to-cast? operations easily and efficiently; if the primitive is cast-else-throw, then the is-safe-to-cast? operation _must_ (as you noted) be provided by the language in a way that doesn't internally generate an exception, for
performance reasons.

-RB

November 24, 2001
"Russell Borogove" <kaleja@estarcion.com> wrote in message news:3BFFFBB3.4070707@estarcion.com...

> It may or may not be an error. Say we're talking about game code, and you're iterating over a collection of objects derived from class Entity, checking to see if they're castable to class ThinkingEntity, and if so, calling their Think() method. There are any number of good reasons to maintain all your entities in a single collection even though they're not completely compatible in some contexts. The alternative is to bloat the base class with a bunch of virtual functions which will be no-op in the majority of cases. (Not to mention that sometimes you won't be allowed to mess with the base class.)

IMHO it's better to make a separate operator to check for the class. Again, an excelent (IMHO) implementation of this is Delphi:

    Class(object)    // cast to Class, no type-check
    object as Class  // cast to Class, throw exception on error
    object is Class  // true if object is instance of Class

So to call ThinkingEntity.Think(), you'd require the following code, supposing that "is" operator is supported in D:

    if (entity is ThinkingEntity)
        entity.Think();

Your code would look very similar:

    if (cast(ThinkingEntity) Entity)
        entity.Think();

So no real advantage here.

> My point is that from a single cast-else-null primitive, you can build cast-else-throw and and is-safe-to-cast? operations easily and efficiently; if the primitive is cast-else-throw, then the

The problem is that every cast operation must be wrapped in an if-block to throw exceptions. This is like, say, wrapping each C function call checking if it returns an error code and throwing an exception.

IMHO, typechecking and typecasting should be _separate_ operations,
not mixed. Because typecasting is usually performed on the generic
pointer actually pointing to the child class when you know for sure
that it does, and typechecking is used when you don't know what object
your pointer references. These are two distinct things, let's not
mix them.

> is-safe-to-cast? operation _must_ (as you noted) be provided by the language in a way that doesn't internally generate an exception, for performance reasons.

BTW I've just thought that this operation is already supported by D due to its RTTI system:

    if (entity.class == ClassThinkingEntity)
        entity.Think();

Personally, I like the "is" operator more, but even now D already has support for typechecking.


November 24, 2001
Pavel Minayev wrote:

> IMHO, typechecking and typecasting should be _separate_ operations,
> not mixed. Because typecasting is usually performed on the generic
> pointer actually pointing to the child class when you know for sure
> that it does, and typechecking is used when you don't know what object
> your pointer references. These are two distinct things, let's not
> mix them.


It's possible that I've been poisoned by years of working with
functions that return a pointer or NULL on failure, but that's a
familiar way for me to frame the idiom "if object supports X() then
do X() on object," so we may just be up against personal style
issues here.


> BTW I've just thought that this operation is already supported by
> D due to its RTTI system:
> 
>     if (entity.class == ClassThinkingEntity)
>         entity.Think();
> 
> Personally, I like the "is" operator more, but even now D already
> has support for typechecking.


But we need to know if the entity is a ThinkingEntity or any class
derived from that.


The class library I'm working with at my job has two separate
operations (macros, actually) -- IsA(), which checks exact class membership, and IsKindOf(), which checks for membership
in any derived class. 


Those would be the minimum primitives necessary in conjunction
with a throwing cast to support the idiom.

-RB

November 25, 2001
"Russell Borogove" <kaleja@estarcion.com> wrote in message news:3C0003D0.9070305@estarcion.com...

> It's possible that I've been poisoned by years of working with functions that return a pointer or NULL on failure, but that's a familiar way for me to frame the idiom "if object supports X() then do X() on object," so we may just be up against personal style issues here.

It's a common style that I use as well, I just ain't satisfied with the syntax.

> But we need to know if the entity is a ThinkingEntity or any class derived from that.

Oh yes, I missed that. However, I'm pretty sure that classes of classes will have some way to determine the parent, for example:

    if (entity.class.extends(ClassThinkingEntity)) ...

Or sumthing like that. Probably Walter will tell us if this works or not as he comes by this thread =)

> The class library I'm working with at my job has two separate
> operations (macros, actually) -- IsA(), which checks exact
> class membership, and IsKindOf(), which checks for membership
> in any derived class.
>
> Those would be the minimum primitives necessary in conjunction with a throwing cast to support the idiom.

In most cases, you actually use IsKindOf() or its equvalent.
So I believe the exact typechecking could be left in its current
form, and base class check should of course be introduced,
hopefully in form of "is" operator.


« First   ‹ Prev
1 2 3 4