On Friday, 11 October 2013 at 21:49:50 UTC, Jonathan M Davis wrote:
On Friday, October 11, 2013 23:06:53 luminousone wrote:
On Friday, 11 October 2013 at 19:54:39 UTC, Jonathan M Davis

wrote:
> On Friday, October 11, 2013 21:19:29 luminousone wrote:
>> Using casts that way won't always be correct, it would be
>> better
>> to use reflection in some way if possible.
> > The only reason that the casts wouldn't be correct would be > if
> the class
> overrode opCast for the type that you're casting to or had an
> alias this
> declaration for it. Using casting for "instanceOf" is
> considered the standard
> and correct way to do it. But if you're being paranoid about
> the possibility
> of a conversion being defined with opCast or alias this, then
> yes, you need to
> use typeid.
> > - Jonathan M Davis

import std.stdio;

bool instanceOf(A, B)(B value) {
return !!cast(A)value;
}

class e {
}

class f : e {

}

class g {

}


void main() {
int a;
float b;
char c;

e E;
f F;
g G;

assert( 1.instanceOf!int, "1");
assert( a.instanceOf!int, "a"); // fails here ?!?
assert( b.instanceOf!int, "b");
assert( c.instanceOf!int, "c");

assert( E.instanceOf!e , "e"); // fails here !??
assert( F.instanceOf!e , "f");
assert( G.instanceOf!e , "g"); // fails as expected
}


Seems to be problems, at least with quick testing using rdmd.
Using casts seems terribly hackish, I would think that some sort
of reflection should be much safer/correct way todo this.

Two things:

1. Casting to determine the type of a variable only makes sense with classes. The idea is that casting a reference to a particular class will result in null if the cast fails. That doesn't work at all with types that aren't classes.

2. All of your objects are null. Of course the cast is going to fail. You need to be operating on actual instances. The whole point of casting is to check the actual type of an object at runtime. It's a completely different use case from using compile-time reflection on two types to see whether one is a base class of the other. And usually all that's done for that is to see whether one implicitly converts to the other, which is(DerivedClass : BaseClass) will do for you. The only reason to use compile-time reflection is if you're want to make sure that DerivedClass doesn't implicitly convert to BaseClass via alias this instead of by actually being a class derived from BaseClass.

I'd also change the implementation of instanceOf to something like

bool instanceOf(A, B)(B value)
 if(is(A == class) && is(B == class))
{
 return cast(A)value !is null;
}

since it doesn't rely on the conversion to bool that ! does and is more
explicit that way, but the other version will work.

- Jonathan M Davis

The inability to handle null is pretty big, specially considering that at not point is the class instance itself cared about!, Again this should be done via reflection, this method above is hackish at best.

perhaps,

bool instanceOf(A, B)( )
   if( is( A == class ) && is( B == class ) ) {
   if( __traits( isSame, A, B ) )
      return true;
   foreach( k, v ; BaseClassesTuple!A ) {
      if( __traits(isSame, B, v ) )
         return true;
   }
   return false;
}

Reply via email to