Справочное руководство Ada 2012
3.8.1 Разделы вариантов и дискретные варианты
Тип записи с разделом variant_part определяет альтернативные списки компонентов. Каждый variant определяет компоненты для значения или значений дискриминанта, охватываемых его discrete_choice_list.
Синтаксис
Правила разрешения имен
discriminant_direct_name должен разрешаться как ссылка на дискриминант (называемый дискриминантом раздела variant_part), указанный в known_discriminant_part полного объявления типа full_type_declaration, содержащего variant_part. Ожидаемый тип для каждого discrete_choice в variant — это тип дискриминанта variant_part.
Правила легальности
Дискриминант variant_part должен быть дискретного типа.
Выражения choice_expression, subtype_indication и range, указанные как discrete_choice в variant_part должны быть статическими. discrete_choice others должен быть указан один раз в discrete_choice_list, и такой discrete_choice_list, если он присутствует, должен быть последним в охватывающем конструкте.
discrete_choice определён как охватывающий значение в следующих случаях:
- Выбор discrete_choice, который является choice_expression, охватывает значение, если это значение равно значению choice_expression, преобразованному к ожидаемому типу.
- Выбор discrete_choice, который является subtype_indication, охватывает все значения (возможно, ни одного), принадлежащие подтипу и удовлетворяющие статическим предикатам подтипа (см. 3.2.4).
- Выбор discrete_choice, который является range, охватывает все значения (возможно, ни одного), принадлежащие диапазону.
- Выбор discrete_choice others охватывает все значения его ожидаемого типа, которые не охватываются предыдущими discrete_choice_list того же конструкта.
discrete_choice_list охватывает значение, если одно из его discrete_choice охватывает это значение.
Возможные значения дискриминанта variant_part должны быть охвачены следующим образом:
- Если дискриминант имеет статический ограниченный скалярный подтип, то, за исключением внутри экземпляра генерируемого блока, каждый не-others discrete_choice должен охватывать только значения в этом подтипе, которые удовлетворяют его предикатам, и каждое значение этого подтипа, удовлетворяющее его предикатам, должно быть охвачено каким-то discrete_choice (явным образом или с помощью others);
- Если тип дискриминанта является потомком генерируемого формального скалярного типа, то variant_part должен содержать discrete_choice others;
- В противном случае каждое значение базового диапазона типа дискриминанта должно быть охвачено (явным образом или с помощью others).
Два различных discrete_choice раздела variant_part не должны охватывать одно и то же значение.
Статическая семантика
Если список компонентов component_list variant задан как null, то вариант не имеет компонентов.
Дискриминант variant_part называется управляющим variant_part и его variantов. Кроме того, дискриминант производного типа управляет variant_part и его variantов, если он соответствует (см. 3.7) дискриминанту variant_part.
Динамическая семантика
Значение записи содержит значения компонентов конкретного variant только в том случае, если значение управляющего дискриминанта variant охватывается discrete_choice_list variantа. Это правило, в свою очередь, относится к любому другому variant, который сам включён в список компонентов данного variant.
Когда объект дискриминированного типа T инициализируется по умолчанию, Constraint_Error возникает, если ни один discrete_choice_list ни одного variant раздела variant_part типа T не охватывает значение дискриминанта, управляющего variant_part. Когда variant_part появляется в списке компонентов component_list другого variant V, это условие проверяется только если значение дискриминанта, управляющего V, охватывается discrete_choice_list V.
Примеры
Пример типа записи с разделом варианта:
type Device is (Printer, Disk, Drum);
type State is (Open, Closed);
type State is (Open, Closed);
type Peripheral(Unit : Device := Disk) is
record
Status : State;
case Unit is
when Printer =>
Line_Count : Integer range 1 .. Page_Size;
when others =>
Cylinder : Cylinder_Index;
Track : Track_Number;
end case;
end record;
record
Status : State;
case Unit is
when Printer =>
Line_Count : Integer range 1 .. Page_Size;
when others =>
Cylinder : Cylinder_Index;
Track : Track_Number;
end case;
end record;
Примеры типов записей:
тип Drum_Unit является Peripheral(Drum);
тип Disk_Unit является Peripheral(Disk);
тип Disk_Unit является Peripheral(Disk);
Примеры ограниченных переменных записей:
Writer : Peripheral(Unit => Printer);
Archive : Disk_Unit;
Archive : Disk_Unit;