Safer casts

Janice Caron caron800 at googlemail.com
Fri May 9 01:15:06 PDT 2008


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?



More information about the Digitalmars-d mailing list