Cast Object - get null

Jonathan M Davis jmdavisProg at gmx.com
Wed Apr 18 16:43:07 PDT 2012


On Thursday, April 19, 2012 00:49:29 Namespace wrote:
> Too early happy, now it seems opEquals wouldn't be called...
> I tried this again:
> 
> U opCast(U)() const if (is(Unqual!U == Vector2D!byte) ||
> is(Unqual!U == Vector2D!ubyte) ||
> is(Unqual!U == Vector2D!short) ||
> is(Unqual!U == Vector2D!ushort) ||
> is(Unqual!U == Vector2D!int) ||
> is(Unqual!U == Vector2D!uint) ||
> is(Unqual!U == Vector2D!long) ||
> is(Unqual!U == Vector2D!ulong) ||
> is(Unqual!U == Vector2D!float) ||
> is(Unqual!U == Vector2D!double) ||
> is(Unqual!U == Vector2D!real))
> {
> return U(this.x, this.y);
> }
> 
> And normal casts works perfectly but what should i do if i get
> Object like in opEquals?
> I think you want me to say what I understand now slowly: it does
> not work with Object. Isn't it?
> It's a very unhappy solution to call
> 
> if (vs == Vector2s(vf)) as simply if (vs == vf)
> 
> If there any other solutions or any ideas to fix my solution in
> my previous post?

It looks like you're dealing with an opCast bug - either 
http://d.puremagic.com/issues/show_bug.cgi?id=5747 or a variant of it.

If you declare another overload of opCast:

 Object opCast(T)() const
 if(is(Unqual!T == Object))
 {
 return this;
 }

then it should work.

I would also point out that it's really bizarre that you're using classes 
here. You definitely seem to be trying to treat them as value types and don't 
need polymorphism at all. So, I'd really advise using structs. However, if you 
did, then you definitely would have to use explict casts with opEquals, because 
it would require the exact type rather than Object. So, if you're insistent on 
not needing to cast, then structs aren't going to do what you want. But given 
that you're dealing with vectors of floats and ints which aren't implicitly 
convertible (or at least, float isn't implicitly convertible to int), it would 
make perfect sense to expect to have to cast them to compare them or have them 
do anything with each other, since that's what happens with the built-in 
types.

Also, there's no need to check for null in opEquals. == actually gets 
translated to this:

bool opEquals(Object lhs, Object rhs)
{
 // If aliased to the same object or both null => equal
 if (lhs is rhs) return true;

 // If either is null => non-equal
 if (lhs is null || rhs is null) return false;

 // If same exact type => one call to method opEquals
 if (typeid(lhs) is typeid(rhs) || typeid(lhs).opEquals(typeid(rhs)))
 return lhs.opEquals(rhs);

 // General case => symmetric calls to method opEquals
 return lhs.opEquals(rhs) && rhs.opEquals(lhs);
}

So, the issues of whether you're comparing an object against itself or where 
the object is null are taken care of for you. It also makes opEquals more 
correct by enforcing that it's equal in both directions when the types aren't 
the same.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list