Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TCustomAttribute - "Constant expression expected" compile error

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]);
...
like image 648
iamjoosy Avatar asked Jan 23 '12 17:01

iamjoosy


2 Answers

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.

like image 68
David Heffernan Avatar answered Sep 28 '22 06:09

David Heffernan


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

like image 22
Uwe Raabe Avatar answered Sep 28 '22 06:09

Uwe Raabe