Johan
Johan

Reputation: 76743

How to trigger a compile-time error when using GetTypeKind

In XE7 we have the new compiler intrinsic function GetTypeKind (as yet undocumented) that allows us to extract the flavor of a type at compile time.

The following code will generate a run-time error if the wrong type is used:

//make sure T is a procedure/function
procedure TDetours<T>.CheckTType;
{$IF CompilerVersion >= 28}
begin
  // XE7 and up:Resolve all tests at compiletime.
  if (Sizeof(T) <> Sizeof(Pointer)) or (GetTypeKind(T) <> tkProcedure) then begin
    raise DetourException.Create('T must be a procedure or function');
  end;
{$ELSE}
  //Code for pre-XE7 versions
{$ENDIF}
end;

I want the compiler to generate a compile-time error if the correct type kind is not used.
This allows be to catch any errors at an earlier stage. Is this possible?

My line of thinking is as follows:
- If the test is false then the code inside the test does not get generated.
- If the test is true then code does get generated.

Is there some code that I can put into the test that will trip up the compiler when generating code, but does not make the parser stop working?

Upvotes: 4

Views: 399

Answers (1)

David Heffernan
David Heffernan

Reputation: 613461

In XE7 we have the new compiler intrinsic function GetTypeKind (as yet undocumented) that allows us to extract the flavor of a type at compile time.

In order for you to be able to do this, you would need to be able to put GetTypeKind into a conditional expression. So that you might write code like this:

{$IF GetTypeKind(T) <> tkProcedure}
  {$Message Fatal 'Invalid type'}
{$ENDIF}

But the compiler does not accept this. The compiler requires the expression in the $IF conditional to be a constant expression, and GetTypeKind(T) <> tkProcedure is not.

I want the compiler to generate a compile-time error if the correct type kind is not used. This allows be to catch any errors at an earlier stage. Is this possible?

This is not possible. The only mechanism you have available is generic constraints. And generic constraints do not have sufficient granularity to specify the constraint that you require.

I think that your best bet is to put an assertion in the class constructor. It would look like this:

class constructor TDetours<T>.CreateClass;
begin
  Assert(Sizeof(T) = Sizeof(Pointer));
  Assert(GetTypeKind(T) = tkProcedure);
end;

Upvotes: 3

Related Questions