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]);
...
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.
This is a known limitation. TGUID is declared as a record type and there is no way to make a record constant expression.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With