【问题标题】:How to trigger a compile-time error when using GetTypeKind使用 GetTypeKind 时如何触发编译时错误
【发布时间】:2015-04-08 15:12:30
【问题描述】:

在 XE7 中,我们有新的编译器内部函数 GetTypeKind(尚未记录),它允许我们在编译时提取类型的味道。

如果使用了错误的类型,以下代码将产生运行时错误:

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

如果没有使用正确的类型类型,我希望编译器生成编译时错误
这允许在早期阶段捕获任何错误。 这可能吗?

我的思路如下:
- 如果测试为假,则不会生成测试中的代码。
- 如果测试为真,则生成代码。

是否有一些代码可以放入测试中,在生成代码时会使编译器跳闸,但不会使解析器停止工作?

【问题讨论】:

  • 可惜不可能,但如果没有错误,至少不会生成代码。

标签: delphi delphi-xe7 type-safety


【解决方案1】:

在 XE7 中,我们有新的编译器内部函数 GetTypeKind(尚未记录),它允许我们在编译时提取类型的味道。

为了让您能够做到这一点,您需要能够将GetTypeKind 放入条件表达式中。这样您就可以编写如下代码:

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

但是编译器不接受这个。编译器要求$IF条件中的表达式是常量表达式,而GetTypeKind(T) &lt;&gt; tkProcedure不是。

如果没有使用正确的类型类型,我希望编译器生成编译时错误。这允许在早期阶段捕获任何错误。这可能吗?

这是不可能的。您唯一可用的机制是通用约束。并且通用约束没有足够的粒度来指定您需要的约束。

我认为最好的办法是在类构造函数中放置一个断言。它看起来像这样:

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

【讨论】:

  • 我已更新问题以使我的意图更清晰。
  • 根据 Stefan Glienke GetTypeKind 确实在编译时解析,请参阅:delphisorcery.blogspot.com/2014/10/…
  • 很公平。但是你仍然不能用它做一个常量表达式。
  • 我怀疑编译器会为所有代码路径生成代码,并且链接器会消除那些从未执行过的代码路径。如果是这样的话,那确实是没有办法做到的,真可惜,
  • 我不认为这个细节是相关的。您根本没有机会使用 Pascal if,因为解析器必须解析您的所有代码。您所希望的只是使用条件,因为这是阻止解析器解析源文件中代码的唯一方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 2014-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
相关资源
最近更新 更多