Safer casts

Robert Fraser fraserofthenight at gmail.com
Fri May 9 11:25:55 PDT 2008


janderson wrote:
> 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

I think Janice mentioned that it would work exactly like that.



More information about the Digitalmars-d mailing list