TCustomAttribute - ошибка компиляции «Ожидается постоянное выражение» - PullRequest
6 голосов
/ 23 января 2012

Учитывая следующий фрагмент кода:

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]);
...

Ответы [ 2 ]

7 голосов
/ 23 января 2012

Соответствующий раздел документации по атрибутам таков:

Важно понимать, что значения, передаваемые в конструктор атрибута, должны быть константными выражениями.Поскольку эти значения должны быть встроены непосредственно в результирующий двоичный файл, невозможно передать выражение, требующее оценки во время выполнения.Это накладывает некоторые ограничения на информацию, которая может быть передана в атрибут во время компиляции:

  • Допускаются только константные выражения, включая наборы, строки и порядковые выражения.
  • outПараметры var и нельзя использовать, поскольку они требуют оценки адресов переданных параметров во время выполнения.
  • Встроенный оператор Addr () и оператор @ нельзя использовать.
  • Оператор TypeInfo () может бытьиспользуется для передачи информации о типе, поскольку адреса блоков RTTI известны во время компиляции.
  • Разрешены ссылки на классы, поскольку адреса метаклассов (как в случае TypeInfo ()) известны во время компиляции.

Ключевым моментом является то, что константное выражение является техническим термином Паскаля, который отличается от константы.Я подозреваю, что это корень путаницы.

Поскольку невозможно иметь постоянное выражение, которое можно передать в TGUID, вам не повезло с вашим атрибутом.Действительно, также невозможно получить константное выражение, которое можно передать в параметр открытого массива.

Я полагаю, что вы можете использовать строковое представление GUID для решения головоломки, но это оставит васс беспорядочным дублированием и невозможностью передавать массивы идентификаторов GUID.

1 голос
/ 23 января 2012

Это известное ограничение.TGUID объявлен как тип записи, и нет способа сделать запись константным выражением.

...