Справочник Ada 95
3.7 Дискриминанты
Составной тип (кроме массива) может иметь дискриминанты, которые параметризуют тип. known_discriminant_part указывает дискриминанты составного типа. Дискриминант объекта — это компонент объекта, который является либо дискретного типа, либо типа доступа. unknown_discriminant_part в объявлении частичного представления типа указывает, что дискриминанты типа неизвестны для данного представления; все подтипы такого частичного представления являются неопределенными подтипами.
Синтаксис
discriminant_part ::= unknown_discriminant_part | known_discriminant_part
unknown_discriminant_part ::= (<>)
known_discriminant_part ::=
(discriminant_specification {; discriminant_specification})
(discriminant_specification {; discriminant_specification})
discriminant_specification ::=
defining_identifier_list : subtype_mark [:= default_expression]
| defining_identifier_list : access_definition [:= default_expression]
defining_identifier_list : subtype_mark [:= default_expression]
| defining_identifier_list : access_definition [:= default_expression]
default_expression ::= expression
Правила разрешения имен
Ожидаемый тип для default_expression в discriminant_specification соответствует типу соответствующего дискриминанта.
Правила допустимости
discriminant_part разрешен только в объявлении составного типа, не являющегося массивом (включая формальные типы обобщений). Тип, объявленный с known_discriminant_part, называется дискриминируемым типом, как и тип, унаследовавший (известные) дискриминанты.
Подтип дискриминанта может быть определён subtype_mark, в этом случае subtype_mark должен обозначать дискретный или тип доступа, или он может быть определен access_definition (в этом случае subtype_mark access_definition может обозначать любой тип подтипа). Дискриминант, определённый access_definition, называется дискриминантом доступа и имеет анонимный общий тип доступа к переменной, подтип которого обозначен subtype_mark access_definition.
discriminant_specification для дискриминанта доступа должен появляться только в объявлении задачи или защищенного типа, или для типа с ключевым словом limited в его (полном) определении или в определении одного из его предков. Помимо мест, где обычно применяются правила допустимости (см. 12.3), это правило применяется также в частях для примеров генерических единиц.
Default_expression предоставляется либо для всех, либо ни для одного дискриминанта known_discriminant_part. Default_expression не допускаются в known_discriminant_part в объявлении помеченного типа или формального типа обобщения.
Для типа, определенного derived_type_definition, если в его объявлении задан known_discriminant_part, то:
- Родительский подтип должен быть ограниченным;
- Если родительский тип не является помеченным типом, то каждый дискриминант производного типа должен использоваться в ограничении, определяющем родительский подтип;
- Если в ограничении, определяющем подтип-родитель, используется дискриминант, то подтип дискриминанта должен быть статически совместим (см. 4.9.1) с подтипом соответствующего дискриминанта родителя.
Тип default_expression, если таковой имеется, для дискриминанта доступа должен быть преобразуем в анонимный тип доступа дискриминанта (см. 4.6).
Статическая семантика
discriminant_specification объявляет дискриминант; subtype_mark обозначает его подтип, если это не дискриминант доступа, в этом случае подтип дискриминанта является анонимным подтипом доступа к переменной, определённым access_definition.
Для типа, определённого derived_type_definition, каждый дискриминант родительского типа либо наследуется, либо ограничен равенством некоторому новому дискриминанту производного типа, либо ограничен значением выражения. Если дискриминант наследуется или ограничен равенством некоторому новому дискриминанту, то родительский дискриминант и дискриминант производного типа называются соответствующими. Два дискриминанта также соответствуют, если есть общий дискриминант, к которому они оба соответствуют. Дискриминант соответствует самому себе. Если дискриминант родительского типа ограничен конкретным значением derived_type_definition, то этот дискриминант называется указанным этим derived_type_definition.
Ограничение, которое появляется в определении типизированного типа, зависит от дискриминанта типа, если оно называет дискриминант как границу или значение дискриминанта. component_definition зависит от дискриминанта, если его constraint зависит от дискриминанта или от дискриминанта, который ему соответствует.
Компонент зависит от дискриминанта, если:
- Его component_definition зависит от дискриминанта; или
- Он объявлен в variant_part, который управляется дискриминантом; или
- Это компонент, унаследованный в рамках derived_type_definition, и constraint parent_subtype_indication зависит от дискриминанта; или
- Это подкомпонент компонента, который зависит от дискриминанта.
Каждое значение типизированного типа включает значение для каждого компонента типа, который не зависит от дискриминанта; это включает сами дискриминанты. Значения дискриминантов определяют, какие другие значения компонентов присутствуют в значении типизированного типа.
Тип, объявленный с known_discriminant_part, имеет известные дискриминанты; его первый подтип не ограничен. Тип, объявленный с unknown_discriminant_part, имеет неизвестные дискриминанты. Тип, объявленный без discriminant_part, не имеет дискриминантов, если это не производный тип; если производный, такой тип имеет тот же вид дискриминантов (известные, неизвестные или отсутствующие) что и родительский (или предковый) тип. Тип помеченного класса также имеет неизвестные дискриминанты. Любой подтип типа с неизвестными дискриминантами является неограниченным и неопределённым подтипом (см. 3.2 и 3.3).
Динамическая семантика
access_definition обрабатывается, когда значение соответствующего дискриминанта доступа определяется, либо путём оценки default_expression, либо путём обработки discriminant_constraint. Обработка access_definition создаёт анонимный тип доступа. При оценке выражения, определяющего дискриминант доступа, оно преобразуется в этот анонимный тип доступа (см. 4.6).
ПРИМЕЧАНИЯ
50 Если типизированный тип имеет default_expressionы для своих дискриминантов, то разрешены неограниченные переменные типа, и значения дискриминантов могут быть изменены присваиванием такой переменной. Если значения по умолчанию не указаны для дискриминантов, то все переменные типа ограничены, либо явным ограничением, либо своим начальным значением; значения дискриминантов такой переменной не могут быть изменены после инициализации.
51 default_expression для дискриминанта типа вычисляется при создании объекта неограниченного подтипа типа.
52 Присваивание дискриминанту объекта (после его инициализации) запрещено, так как имя дискриминанта является константой; не допускаются ни операторы присваивания, ни присваивания, свойственные передаче в качестве параметра in out или out. Однако следует отметить, что значение дискриминанта может быть изменено присваиванием окружающему объекту, предполагая, что это неограниченная переменная.
53 Дискриминант, являющийся типом с именованным доступом, не называется дискриминантом доступа; это термин используется только для дискриминантов, определённых с помощью access_definition.
Примеры
Примеры типов с дискриминантами:
type Buffer(Size : Buffer_Size := 100) is -- см. 3.5.4
record
Pos : Buffer_Size := 0;
Value : String(1 .. Size);
end record;
record
Pos : Buffer_Size := 0;
Value : String(1 .. Size);
end record;
type Matrix_Rec(Rows, Columns : Integer) is
record
Mat : Matrix(1 .. Rows, 1 .. Columns); -- см. 3.6
end record;
record
Mat : Matrix(1 .. Rows, 1 .. Columns); -- см. 3.6
end record;
type Square(Side : Integer) is new
Matrix_Rec(Rows => Side, Columns => Side);
Matrix_Rec(Rows => Side, Columns => Side);
type Double_Square(Number : Integer) is
record
Left : Square(Number);
Right : Square(Number);
end record;
record
Left : Square(Number);
Right : Square(Number);
end record;
type Item(Number : Positive) is
record
Content : Integer;
-- ни один компонент не зависит от дискриминанта
end record;
record
Content : Integer;
-- ни один компонент не зависит от дискриминанта
end record;