Traits

luminousone rd.hunt at gmail.com
Fri Oct 11 15:54:48 PDT 2013


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


More information about the Digitalmars-d-learn mailing list