TCustomAttribute-“期望的常量表达式”编译错误

发布于 2024-12-28 21:06:40 字数 649 浏览 3 评论 0原文

给出以下代码片段:

type
  MyIntf = interface
    ['{C6184693-663E-419F-B2DA-4DA1A0E33417}']
    procedure Foo;
  end;

  InvisiblePropInterfaces = class(TCustomAttribute)
  private
    FGUIDS: array of TGUID;
  public
    constructor Create(const GUIDS: array of TGUID);
  end;

  [InvisiblePropInterfaces([MyIntf])]  // <-- Constant expression expected error
  TMyClass = class(TInterfacedObject, MyIntf)
    procedure Foo;
  end;

为什么编译器认为这不是常量表达式? 但鉴于我像这样使用 InvisiblePropInterfaces,编译器就很高兴?

...
var
  I: InvisiblePropInterfaces;
begin
  I:= InvisiblePropInterfaces.Create([MyIntf]);
...

Given the following code snippet:

type
  MyIntf = interface
    ['{C6184693-663E-419F-B2DA-4DA1A0E33417}']
    procedure Foo;
  end;

  InvisiblePropInterfaces = class(TCustomAttribute)
  private
    FGUIDS: array of TGUID;
  public
    constructor Create(const GUIDS: array of TGUID);
  end;

  [InvisiblePropInterfaces([MyIntf])]  // <-- Constant expression expected error
  TMyClass = class(TInterfacedObject, MyIntf)
    procedure Foo;
  end;

Why does the compiler think this is not a constant expression ?
But given that I use InvisiblePropInterfaces like this, the compiler is just happy?

...
var
  I: InvisiblePropInterfaces;
begin
  I:= InvisiblePropInterfaces.Create([MyIntf]);
...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你爱我像她 2025-01-04 21:06:40

属性文档的相关部分如下:

重要的是要理解传递给属性构造函数的值必须是常量表达式。由于这些值必须直接嵌入到生成的二进制文件中,因此不可能传递需要运行时求值的表达式。这对编译时可以传递给属性的信息提出了一些限制:

  • 仅允许使用常量表达式,包括集合、字符串和序数表达式。
  • 不能使用 out 和 var 参数,因为它们需要运行时评估传递参数的地址。
  • 不能使用 Addr() 内部函数和 @ 运算符。
  • TypeInfo() 运算符可用于传递类型信息,因为 RTTI 块地址在编译时已知。
  • 允许类引用,因为元类地址(如 TypeInfo() 的情况)在编译时已知。

关键点是 常量表达式 是一个 Pascal 技术术语,而不是与常数相同。我怀疑这就是混乱的根源。

由于不可能有可传递给 TGUID 的常量表达式,因此您的属性不走运。事实上,不可能有一个可以传递给开放数组参数的常量表达式。

我想您可以使用 GUID 的字符串表示形式来解决这个难题,但这会给您带来混乱的重复,并且无法传递 GUID 数组。

The pertinent section of the attributes documentation is this:

It is important to understand that the values passed to the attribute's constructor must be constant expressions. Because those values must be embedded directly into the resulting binary, it is impossible to pass an expression that requires run-time evaluation. This raises a few limitations to the information that can be passed to the attribute at compile time:

  • Only constant expressions are allowed, including sets, strings, and ordinal expressions.
  • out and var parameters cannot be used, because they require run-time evaluation of addresses of passed parameters.
  • Addr() intrinsic and @ operator cannot be used.
  • The TypeInfo() operator can be used to pass type information, because the RTTI block addresses are known at compile time.
  • Class references are allowed, because the metaclass addresses (as the case of TypeInfo()) are known at compile time.

The key point is that a constant expression is a technical Pascal term that is not the same thing as a constant. I suspect that this is the root of the confusion.

Since it is not possible to have a constant expression that can be passed to a TGUID, you are out of luck with your attribute. Indeed it is just as impossible to have a constant expression that can be passed to an open array parameter.

I suppose that you could use the string representation of the GUID to solve the conundrum but that will leave you with messy duplication and an inability to pass arrays of GUIDs.

单挑你×的.吻 2025-01-04 21:06:40

这是一个已知的限制。 TGUID 被声明为记录类型,并且无法创建记录常量表达式。

This is a known limitation. TGUID is declared as a record type and there is no way to make a record constant expression.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文