Safer casts

Robert Fraser fraserofthenight at gmail.com
Fri May 9 11:16:27 PDT 2008


I'm sorry if this post sounds argumentative, but I disagree strongly 
with pretty much everything in this post. So no hard feelings, peace, 
respect, all that ;-P.

Janice Caron wrote:
> Better, safer casts have been requested before - in fact I routinely
> see that request on the monthly "D wishlist" that goes round. 

I doubt any of the suggestions include "at the expense of the current 
cast". If all these were implemented, it would be a significant 
cognitive load on the programmer, and D is already a fairly complex 
language.

Also, should getting rid of keywords really be a design goal? Only 
Walter (and you, apparently; no disrespect) seem to think so.

> But
> here's a fairly concrete suggestion as to what the syntax might be.
> And as a bonus, we'd get rid of the "cast" keyword, thus reducing the
> keyword count by one. So, here are the various types of transformation
> I suggest:
> 
> 
> (*) Build a new instance with a different memory layout, but with the
> same value. (For example, casting double to int). For lossless
> conversions, this can happen implicitly, but for lossy conversions, an
> explicit cast is necessary. For D, I suggest
> 
>     to!(T)(x)
> 
> where to! is a template function provided by std.conv (not a keyword).
> to! already performs many conversions. Throwing in the basics like
> to!(int)(double) would be an obvious extension.

Ick! That means another identifier that needs to be a compiler built-in 
thus increasing coupling between the compiler and the standard library. 
Since it's not something the template can actually handle, why should it 
be in there rather a special construct in the core language?

> (*) Use RTTI to cast up and down the class heirarchy. In C++, this
> would be dynamic_cast<T>(x). For D, I suggest two things. Firstly, the
> cast:
> 
>     class!(T)(x)
> 
> to do that actual upcast or downcast - but RTTI dynamic casts can
> fail, so the question arises: What should we do if the cast fails?
> Should we return null, or should we throw an exception. My view is
> that we should throw an exception, but also introduce a new construct
> to test whether or not the cast would be possible in the first place:
> 
>     is!(T)(x)
> 
> which returns bool. is!(T) would be like Java's instanceof. Thus, one
> could write
> 
>     void f(A a)
>     {
>         if (is!(B)a)
>         {
>             B b = class!(B)(a);
>             /*...*/
>         }
>         else if (is!(C)a)
>         {
>             C c = class!(C)(a);
>             /*...*/
>         }
>     }
> 
> etc.

But all this is possible with the current cast system. All you gain is a 
more complex syntax, and since "cast" is a term well-known to 
programmers, you lose a meaningful bit of syntax.

> (*) Reinterpret a bit pattern. In C++, this would be
> reinterpret_cast<T>(x). Without changing the memory layout, or the
> constancy, reinterpret the bits to mean something else. For D, I
> suggest
> 
>     union!(T)(x)

Ditto as above. Just means the person needs to think about something 
else. And why "union", that seems like an arbitrary keyword. WHy not 
"foreach_reverse!(T)(x)" which makes just as much sense.

> (*) Change const to mutable, or invariant to mutable. In C++, this
> would be const_cast<T>(x). There is no equivalent in D, however, in D,
> one can currently write cast(T)x, and constancy will be magically (and
> dangerously) waved away. In the new scheme, I suggest:
> 
>     auto!(T)(x)

How is that better than "cast(T) x;". I guess just because it creates 
the distinction?

> (*) Change const to invariant, or mutable to invariant. Currently, the
> syntax for this is cast(invariant)x, however this has two
> disadvantages: (i) the entire type is made invariant, and you might
> want to invariantize only part of the type, and (ii) cast(T)x also
> works. In other words, (i) is not powerful enough, and (ii) is too
> dangerous. There is no equivalent for this in C++, since C++ has no
> invariance. For D, I suggest:
> 
>     invariant!(T)(x)

Again, how is that any better?
---
Okay, sorry that was so negative. But it just seems that cast() works 
perfectly fine for _all_ those things right now. If what you want is 
safer casting, you can write your own templates to do that.



More information about the Digitalmars-d mailing list