Safer casts

janderson askme at me.com
Fri May 9 08:05:11 PDT 2008


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. 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.
> 
> 
> 
> (*) 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.
> 
> 
> (*) 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)
> 
> 
> (*) 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)
> 
> 
> 
> (*) 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)
> 
> 
> 
> I think that's all bases covered. So in summary we'd have:
> 
>     to!(T)(x)        // convert
>     is!(T)(x)        // is upcast or downcast possible?
>     class!(T)(x)    // upcast or downcast
>     union!(T)(x)    // reinterpret the bits
>     auto!(T)(x)        // remove constancy
>     invariant!(T)(x)    // add invariance
> 
> 
> Those seem reasonably obvious word choices to me. Thoughts?

I think that up casting for classes should be implicit, like it works in 
C++.  Its perfectly ok to upcast and there shouldn't be any warning 
casts around that.  That is actually a very useful feature for genetic 
style coding.  Of course the cast should still work for upcasting, but 
its superfluous.

-Joel



More information about the Digitalmars-d mailing list