Руководство по Ada (Ada 2022)
12.7 Формальные пакеты
Формальные пакеты могут использоваться для передачи пакетов в обобщенную единицу. formal_package_declaration объявляет, что формальный пакет является экземпляром заданного обобщенного пакета. При инстанцировании фактический пакет должен быть экземпляром этого обобщенного пакета.
Синтаксис
formal_package_declaration ::=
с пакет defining_identifier есть новый generic_package_name formal_package_actual_part
[aspect_specification];
с пакет defining_identifier есть новый generic_package_name formal_package_actual_part
[aspect_specification];
formal_package_actual_part ::=
([другие =>] <>)
| [generic_actual_part]
| (formal_package_association {, formal_package_association} [, другие => <>])
([другие =>] <>)
| [generic_actual_part]
| (formal_package_association {, formal_package_association} [, другие => <>])
Любые позиционные formal_package_association должны предшествовать любым именованным formal_package_association.
Правила допустимости
generic_package_name должен обозначать обобщенный пакет (шаблон для формального пакета); формальный пакет является экземпляром шаблона.
generic_formal_parameter_selector_name в formal_package_association должен обозначать generic_formal_parameter_declaration шаблона. Если два или более формальных подпрограммы шаблона имеют то же имя, то именованные ассоциации не разрешены для соответствующих фактических значений.
formal_package_actual_part должен содержать не более одной formal_package_association для каждого формального параметра. Если formal_package_actual_part не включает «другие => <>», каждый формальный параметр без ассоциации должен иметь default_expression или subprogram_default.
Правила соответствия между formal_package_association и формальными параметрами шаблона следующие:
- Если все formal_package_association заданы обобщенными ассоциациями, то explicit_generic_actual_parameter formal_package_association должны быть допустимы для инстанцирования шаблона.
- Если formal_package_association для формального типа T шаблона задается <>, тогда formal_package_association для любого другого generic_formal_parameter_declaration шаблона, который упоминает T напрямую или косвенно, также должна задаваться <>.
Фактический пакет должен быть экземпляром шаблона. Если formal_package_actual_part равно (<>) или (другие => <>), то фактический пакет может быть любым экземпляром шаблона; в противном случае некоторые фактические параметры фактического экземпляра должны соответствовать соответствующим фактическим параметрам формального пакета, определенным следующим образом:
- Если formal_package_actual_part включает generic_associationы, а также ассоциации с <>, то только фактические параметры, явно указанные с помощью generic_associationов, требуются для соответствия;
- В противном случае все фактические параметры должны соответствовать, независимо от того, заданы ли фактические параметры явно или по умолчанию.
Правила соответствия фактических параметров между фактическим экземпляром и формальным пакетом следующие:
- Для формального объекта с режимом in фактические параметры соответствуют, если они являются статическими выражениями с одинаковым значением или статически обозначают одну и ту же константу, или если оба являются литералом null.
- Для формального подтипа фактические параметры соответствуют, если они статически обозначают совпадающие подтипы.
- Для других типов формальных параметров фактические параметры соответствуют, если они статически обозначают одну и ту же сущность.
Для целей сопоставления любой фактический параметр, являющийся именем формального объекта с режимом in, заменяется фактическим выражением формального объекта (рекурсивно).
Статическая семантика
formal_package_declaration объявляет обобщенный формальный пакет.
Видимая часть формального пакета включает первый список basic_declarative_itemов из package_specification. Кроме того, для каждого фактического параметра, который не требует соответствия, копия объявления соответствующего формального параметра шаблона включается в видимую часть формального пакета. Если скопированное объявление относится к формальному типу, копии неявных объявлений примитивных подпрограмм формального типа также включаются в видимую часть формального пакета.
Для целей сопоставления, если фактический экземпляр A сам является формальным пакетом, то фактические параметры A задаются явно или неявно в formal_package_actual_part для A, плюс, для тех, что не указаны, копии формальных параметров шаблона, включенные в видимую часть A.
Примеры
Пример обобщенного пакета с формальными параметрами пакета:
с Ada.Containers.Ordered_Maps; -- см. A.18.6
обобщенный
с пакет Mapping_1 есть новый Ada.Containers.Ordered_Maps(<>);
с пакет Mapping_2 есть новый Ada.Containers.Ordered_Maps
(Key_Type => Mapping_1.Element_Type,
другие => <>);
пакет Ordered_Join есть
-- Предоставьте "соединение" между двумя отображениями
обобщенный
с пакет Mapping_1 есть новый Ada.Containers.Ordered_Maps(<>);
с пакет Mapping_2 есть новый Ada.Containers.Ordered_Maps
(Key_Type => Mapping_1.Element_Type,
другие => <>);
пакет Ordered_Join есть
-- Предоставьте "соединение" между двумя отображениями
подтип Key_Type есть Mapping_1.Key_Type;
подтип Element_Type есть Mapping_2.Element_Type;
подтип Element_Type есть Mapping_2.Element_Type;
функция Lookup(Key : Key_Type) возвращает Element_Type;
...
конец Ordered_Join;
конец Ordered_Join;
Пример инстанцирования пакета с формальными пакетами:
с Ada.Containers.Ordered_Maps;
пакет Symbol_Package есть
пакет Symbol_Package есть
подтип Key_String есть String(1..5);
тип String_Id есть ...
тип String_Id есть ...
тип Symbol_Info есть ...
пакет String_Table есть новый Ada.Containers.Ordered_Maps
(Key_Type => Key_String,
Element_Type => String_Id);
(Key_Type => Key_String,
Element_Type => String_Id);
пакет Symbol_Table есть новый Ada.Containers.Ordered_Maps
(Key_Type => String_Id,
Element_Type => Symbol_Info);
(Key_Type => String_Id,
Element_Type => Symbol_Info);
пакет String_Info есть новый Ordered_Join(Mapping_1 => String_Table,
Mapping_2 => Symbol_Table);
Mapping_2 => Symbol_Table);
Apple_Info : константа Symbol_Info := String_Info.Lookup("Apple");
конец Symbol_Package;