а запись должна быть объявлена
type Codes is (Record_Code, Array_Code);
Ada |
record
case Code is
when Record_Code => R: Rec;
when Array_Code => A: Arr;
end case;
end record;
а запись должна быть объявлена с конкретным дискриминантом, чтобы компилятор точно знал, сколько памяти нужно выделить:
Ada |
S2: S_Type(Array_Code);
Другая возможность — объявить указатель на вариантную запись и проверять дискриминант во время выполнения:
I Ada type Ptr is access S_Type;
Ada |
I:=P.R.I1; --Правильно
I:=P.A(5); -- Ошибка
Первый оператор присваивания правильный, поскольку дискриминант записи P.all — это Record_Code, который гарантирует, что поле R существует; в то же время второй оператор приводит к исключительной ситуации при работе программы, так как дискриминант не соответствует запрошенному полю.
Основное правило для дискриминантов в языке Ada заключается в том, что их можно читать, но не писать, так что нельзя обойти контроль соответствия типов. Это также означает, что память может выделяться в точном соответствии с выбранным вариантом, в отличие от обычного выделения для самого большого варианта.
Неограниченные записи в Ada
В дополнение к ограниченным записям, вариант которых при создании переменной фиксирован, Ada допускает объявление неограниченных записей (unconstrained records), для которых допустимо во время выполнения безопасное с точки зрения контроля типов присваивание, хотя записи относятся к разным вариантам:
S1, S2: S_Type; -- Неограниченные записи
S1 := (Record_Code, 4.5);
S2 := (Array_Code, 1..10 => 17);
S1 := S2; -- Присваивание S1 другого варианта