Cast Object - get null

Jonathan M Davis jmdavisProg at gmx.com
Thu Apr 19 02:51:54 PDT 2012


On Thursday, April 19, 2012 11:27:20 Namespace wrote:
> On Thursday, 19 April 2012 at 09:22:24 UTC, Jonathan M Davis
> 
> wrote:
> > On Thursday, April 19, 2012 11:15:23 Namespace wrote:
> >> A specific Windows bug with opEquals and opCast?
> > 
> > Maybe. Certainly, it's working on my Linux box, so if you're
> > compiling the
> > same code that I am, and you're using 2.059, it definitely
> > sounds like it's a
> > Windows-specific bug.
> > 
> >> My Windows is 64 bit also.
> > 
> > The fact that it's 64-bit shouldn't matter on Windows, because
> > dmd can't
> > generate 64-bit code on Windows yet.
> > 
> > - Jonathan M Davis
> 
> Ok. And what schould i do now? Any patches available for that?
> Otherwise i must cast up to dmd 2.060 explicit as you do in the
> first if condition.

Actually, I just re-ran the code on my box, and it does segfault. Either I 
forgot to run it or I didn't notice the segfault, since it isn't as obvious on 
Linux with all of the other output:

vs.x: 23, vs.y: 42
raw.Vector2D!(short).Vector2D
raw.Vector2D!(short).Vector2D
equal
raw.Vector2D!(float).Vector2D
null
Segmentation fault

What's going wrong is that this cast in opEquals:

        Vector2D!(T) vec = cast(Vector2D!(T)) o;

is failing. The result is null. That's what you'd expect if the built-in cast 
is being used rather than opCast. And if I put print statements in all three 
of the opCasts, none of them are called.

Upon thinking further about it, I believe that the problem is that you're 
casting from _Object_ rather than one of the other instantiations of Vector2D, 
and Object obviously doesn't define an opCast for your type. So, it uses the 
normal, built-in cast, and it fails, because the type that you're attempting 
to cast to is not derived from the one that you're trying to cast to. If you 
could get it to its actual type and _then_ cast it, you could do it. But 
that's a rather nasty problem. After messing with it a bit though, I do 
believe that I've come up with a solution. Change opEquals to this:

    override bool opEquals(Object o) const {
        writeln(o);

        auto vec = castFromObject(o);
        assert(vec !is null);

        writeln(vec);

        return vec.x == this.x && vec.y == this.y;
    }


    private static Vector2D castFromObject(Object o)
    {
        import std.typetuple;
        foreach(U; TypeTuple!(byte, ubyte, short, ushort, int, uint,
                              long, ulong, float, double, real))
        {
            if(auto vec = cast(Vector2D!U)o)
                return cast(Vector2D)vec;
        }

        return null;
    }

I believe that that takes care of the problem.

By the way, inside of a template, you don't need to reuse the template 
arguments when refering to it. So, inside of Vector2D, you can use Vector2D 
instead of Vector2D!T.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list