Thread overview
how to compare the type of a subclass
Nov 21, 2014
Eric
Nov 21, 2014
anonymous
Nov 21, 2014
Eric
Nov 21, 2014
H. S. Teoh
Nov 21, 2014
Eric
Nov 21, 2014
anonymous
November 21, 2014
Suppose I have:

module test;
class X { }
class Y : X { }

Y y = new Y;

X x = y;

assert(is(typeof(x) == test.Y); // this assertion will fail
assert(typeid(x).toString() == "test.Y"); // this assertion will pass

Is there a way I can check the type of x without doing
a string comparison?

-Eric
November 21, 2014
On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote:
>
> Suppose I have:
>
> module test;
> class X { }
> class Y : X { }
>
> Y y = new Y;
>
> X x = y;
>
> assert(is(typeof(x) == test.Y); // this assertion will fail
> assert(typeid(x).toString() == "test.Y"); // this assertion will pass
>
> Is there a way I can check the type of x without doing
> a string comparison?
>
> -Eric

assert(typeid(x) == typeid(Y));
November 21, 2014
On Friday, 21 November 2014 at 22:25:32 UTC, anonymous wrote:
> On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote:
>>
>> Suppose I have:
>>
>> module test;
>> class X { }
>> class Y : X { }
>>
>> Y y = new Y;
>>
>> X x = y;
>>
>> assert(is(typeof(x) == test.Y); // this assertion will fail
>> assert(typeid(x).toString() == "test.Y"); // this assertion will pass
>>
>> Is there a way I can check the type of x without doing
>> a string comparison?
>>
>> -Eric
>
> assert(typeid(x) == typeid(Y));

Thanks.  That works.  I have't quite mastered the whole is/typeof/typeid
thing yet.
November 21, 2014
On Fri, Nov 21, 2014 at 10:30:51PM +0000, Eric via Digitalmars-d-learn wrote:
> On Friday, 21 November 2014 at 22:25:32 UTC, anonymous wrote:
> >On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote:
[...]
> >>Is there a way I can check the type of x without doing
> >>a string comparison?
> >>
> >>-Eric
> >
> >assert(typeid(x) == typeid(Y));
> 
> Thanks.  That works.  I have't quite mastered the whole is/typeof/typeid thing yet.

Binary `is` (i.e., `a is b`) is for comparing two references for equality. It returns true if two class reference point to the same object; false otherwise. But you probably already know this.

Unary `is` (`is(...)`) is a monstrous maze of obscure syntax, that's
best learned on a case-by-case basis. :-) But in this particular case,
it's basically to provide a context for comparing types, since types
aren't actual objects at runtime. So you can't write `if (typeof(a) ==
typeof(b))`, for example, because types aren't objects. Instead, you
have to write `if (is(typeof(a) == typeof(b)))`.

`typeof` is to extract types at compile-time. It returns the *declared* type of the variable (which may not be the most derived class if you assigned a derived object to a base class reference).

`typeid` is to introspect types at runtime. It returns the most derived type of the object, even if the declared type is a base class. The returned type is an actual runtime object -- since at compile-time, the most derived type may not be known, so it's not representable as an actual type at compile-time. Instead, the D runtime returns a TypeInfo object that corresponds with the runtime type of the object. So you don't need to (and shouldn't) use `is(...)` when comparing typeid's.

In short:

To compare (declared) types at compile time:

	is(typeof(x) == typeof(y))	// x has the same (declared) type as y
	is(typeof(x) : typeof(y))	// x implicitly converts to y

To compare (actual) types at runtime:

	typeid(x) == typeid(y)	// x has the same (actual) time as y
	cast(B)x !is null	// x is a derived class instance of base class B

There are many other cases, of course, but these are the pertinent ones in the context of your original question.


T

-- 
Never wrestle a pig. You both get covered in mud, and the pig likes it.
November 21, 2014
On Friday, 21 November 2014 at 22:30:52 UTC, Eric wrote:
> On Friday, 21 November 2014 at 22:25:32 UTC, anonymous wrote:
>> On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote:
[...]
>>> class X { }
>>> class Y : X { }
>>>
>>> Y y = new Y;
>>>
>>> X x = y;
[...]
> I have't quite mastered the whole is/typeof/typeid
> thing yet.

Maybe this helps:

There are two worlds:
* the static world = the compile time world = the world of types
and constant values,
* the dynamic = the run time world = the world of values.

Obviously, there are no variable values in the static world.
Maybe less obviously, there are no types in the dynamic world.

The variable x is statically typed as X. is(...) and typeof(...)
operate on this level. But the object stored in x is being
constructed as a Y at run time. That information is available
through typeid.

typeid(...) is not a type, it's a value of type TypeInfo which
corresponds to a type. typeid(Y) and typeid(x) are TypeInfo
objects both corresponding to the type Y.
November 21, 2014
On Friday, 21 November 2014 at 22:52:54 UTC, H. S. Teoh via Digitalmars-d-learn wrote:
> On Fri, Nov 21, 2014 at 10:30:51PM +0000, Eric via Digitalmars-d-learn wrote:
>> On Friday, 21 November 2014 at 22:25:32 UTC, anonymous wrote:
>> >On Friday, 21 November 2014 at 22:15:37 UTC, Eric wrote:
> [...]
>> >>Is there a way I can check the type of x without doing
>> >>a string comparison?
>> >>
>> >>-Eric
>> >
>> >assert(typeid(x) == typeid(Y));
>> 
>> Thanks.  That works.  I have't quite mastered the whole
>> is/typeof/typeid thing yet.
>
> Binary `is` (i.e., `a is b`) is for comparing two references for
> equality. It returns true if two class reference point to the same
> object; false otherwise. But you probably already know this.
>
> Unary `is` (`is(...)`) is a monstrous maze of obscure syntax, that's
> best learned on a case-by-case basis. :-) But in this particular case,
> it's basically to provide a context for comparing types, since types
> aren't actual objects at runtime. So you can't write `if (typeof(a) ==
> typeof(b))`, for example, because types aren't objects. Instead, you
> have to write `if (is(typeof(a) == typeof(b)))`.
>
> `typeof` is to extract types at compile-time. It returns the *declared*
> type of the variable (which may not be the most derived class if you
> assigned a derived object to a base class reference).
>
> `typeid` is to introspect types at runtime. It returns the most derived
> type of the object, even if the declared type is a base class. The
> returned type is an actual runtime object -- since at compile-time, the
> most derived type may not be known, so it's not representable as an
> actual type at compile-time. Instead, the D runtime returns a TypeInfo
> object that corresponds with the runtime type of the object. So you
> don't need to (and shouldn't) use `is(...)` when comparing typeid's.
>
> In short:
>
> To compare (declared) types at compile time:
>
> 	is(typeof(x) == typeof(y))	// x has the same (declared) type as y
> 	is(typeof(x) : typeof(y))	// x implicitly converts to y
>
> To compare (actual) types at runtime:
>
> 	typeid(x) == typeid(y)	// x has the same (actual) time as y
> 	cast(B)x !is null	// x is a derived class instance of base class B
>
> There are many other cases, of course, but these are the pertinent ones
> in the context of your original question.
>
>
> T

Thanks, this helps a lot.

-Eric