【问题标题】: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 是一个类,它也会编译。
  • 您在记录中缺少什么样的便利?你不可能是指继承之类的吧?

标签: delphi compiler-directives


【解决方案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”只确保它被声明,而不是它是范围内“最接近”的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    相关资源
    最近更新 更多