Fair enough - TB is a type rather an a VMT pointer, so you need to call ClassType on it to get the VMT pointer. However Thaddy's solution doesn't take care of inheritance (a class reference variable set to a subclass of TB should also return true for "is TB").
Here's what I came up with:
program Project1;
uses sysutils;
type
TA = class
end;
TB = class(TA)
end;
TC = class(TB)
end;
TD = class(TA)
end;
TAClass = class of TA;
function ClassReferenceIs(aObjectClass, aTargetClass: TAClass): boolean;
type
PVMT = ^TVMT;
TVMT = packed record
Useless: ptruint;
Useless2: ptruint;
AncestorVMT: pointer;
end;
var
p: pointer;
begin
p := pointer(aObjectClass);
repeat
if p = pointer(aTargetClass) then
begin
Result := true;
exit;
end;
p := PVMT(p)^.AncestorVMT;
until p = nil;
Result := false;
end;
var
AC: TAClass;
begin
AC := TA;
writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // nope
AC := TB;
writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // yep
AC := TC;
writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // yep
AC := TD;
writeln(booltostr(ClassReferenceIs(AC, TB), 'yep', 'nope')); // nope
readln();
end.
I think to be honest though, FPC should support "is" on class references. It's a perfectly sensible thing to want to do, and can use exactly the same algorithm as for class instances.
In fact, it should probably support things like "TB is TA" as well? That may be rather useless, but it still makes sense - when compiling, the type "TB" used as a value is just the VMT pointer of TB.
I see now two people have suggested InheritsFrom, that works wonderfully - thanks.
ahydra