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;
}