我可以在编译器指令中推断出类型的类型吗

Posted

技术标签:

【中文标题】我可以在编译器指令中推断出类型的类型吗【英文标题】:Can I deduce the type of a type in a compiler directive 【发布时间】:2017-06-09 08:17:42 【问题描述】:

是否可以像这样创建条件定义:

$if typeof(TNode) = record
type PNode = ^TNode;
$else
type PNode = TNode;
$end

我为什么要这个? 对于特定问题,我在使用 classrecord 之间交替使用。 出于速度原因,我想使用记录,但为了方便也想使用class

出于这个原因,我在两者之间切换。 显然我可以添加一个$define 语句,但如果能够自动执行它会很好。

【问题讨论】:

无论如何我都会使用 $define 方法,因为我想同时切换记录/类定义。这对我来说似乎更简单。 不,据我所知这是不可能的。但我很想被证明是错误的。 这怎么可能奏效呢? PNode^.SomeField 如果它是一个记录指针,则它是有效的,但对于类引用来说是无意义的。当然,这不是一个普遍有效的替代。 @J...,如果是记录指针,您还可以编写 PNode.SomeField,如果 PNode 是一个类,它也会编译。 您在记录中缺少什么样的便利?你不可能是指继承之类的吧? 【参考方案1】:

虽然我个人推荐一般的 DEFINE 方法,但在记录不是特定大小的情况下,您可能会成功:

$if Sizeof(TNode) <> Sizeof(Pointer)
type PNode = ^TNode;
$else
type PNode = TNode;
$end

好的,我知道这是肮脏的编程,但你一开始就要求这样做。

【讨论】:

请注意,这不是一个通用的解决方案,而是非常专业的。一般来说,如果记录包含的成员的大小发生加起来等于指针的大小,则此操作将失败。例如,如果记录包含一个 32 位的 Integer 或一个 64 位的 Int64。或单个NativeInt。或任何其他类型的组合,加起来最多为 4 或 8 个字节。【参考方案2】:

如果你控制两个TNode的定义,你可以这样做(不需要在同一个单元,但必须引用相同的常量):

const
  NODE_IS_RECORD = False;

type
$if NODE_IS_RECORD
  TNode = record

  end;
  PNode = ^TNode;
$ELSE
  TNode = class

  end;
  PNode = TNode;
$IFEND

如果你只控制 1 个 TNode 声明,你仍然可以这样做:

Unit1
type
  TNode = record

  end;
  PNode = ^TNode;

Unit2
$IF not DECLARED(PNode)
  //if you don't use the unit where TNode is a record, then PNode shouldn't be declared.
  PNode = TNode;
$ENDIF

如果您不控制任何声明,但它们以不同的单位声明(实际上,我认为这是必需的......)并且您从不使用两者,或者使用两者总是意味着您想要使用 PNode 的特定声明:

$IF DECLARED(UnitContainingTNodeAsRecord)
  PNode = ^TNode;
$ELSE
  PNode = TNode;
$IFEND

如果您同时使用两个单元,您可能需要在 TNode 前面加上单元名称。 “DECLARED”只确保它被声明,而不是它是范围内“最接近”的。

我认为这涵盖了大多数情况。

【讨论】:

以上是关于我可以在编译器指令中推断出类型的类型吗的主要内容,如果未能解决你的问题,请参考以下文章

Typescript编译器无法从Promise resolve调用中推断类型

Java中的var关键字

显示推断的 Scala 表达式类型

TypeScript——类型检查机制

仅对lambda表达式的隐式类型推断?为什么?困惑!

TypeScript类型检查机制