Справочник Ada 2012
12.7 Формальные пакеты
Формальные пакеты могут использоваться для передачи пакетов в обобщённый блок. formal_package_declaration объявляет, что формальный пакет является экземпляром заданного обобщённого пакета. При инстанцировании фактический пакет должен быть экземпляром этого обобщённого пакета.
Синтаксис
formal_package_declaration ::=
with package defining_identifier is new generic_package_name formal_package_actual_part
[aspect_specification];
with package defining_identifier is new generic_package_name formal_package_actual_part
[aspect_specification];
formal_package_actual_part ::=
([others =>] <>)
| [generic_actual_part]
| (formal_package_association {, formal_package_association} [, others => <>])
([others =>] <>)
| [generic_actual_part]
| (formal_package_association {, formal_package_association} [, others => <>])
Любые позиционные 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 не включает «others => <>», каждый формальный параметр без ассоциации должен иметь default_expression или subprogram_default.
Правила соответствия между formal_package_association и формальными параметрами шаблона следующие:
- Если все formal_package_association заданы с помощью обобщённых ассоциаций, то explicit_generic_actual_parameters formal_package_associations должны быть допустимы для инстанцирования шаблона.
- Если formal_package_association для формального типа T шаблона задаётся как <>, то formal_package_association для любого другого generic_formal_parameter_declaration шаблона, который упоминает T напрямую или косвенно, также должен быть задан как <>.
Фактический параметр должен быть экземпляром шаблона. Если formal_package_actual_part равен (<>) или (others => <>), то фактический параметр может быть любым экземпляром шаблона; в противном случае некоторые фактические параметры фактического экземпляра должны соответствовать соответствующим фактическим параметрам формального пакета, определяемым следующим образом:
- Если formal_package_actual_part включает generic_associations, а также ассоциации с <>, то только фактические параметры, явно указанные с помощью generic_associations, должны соответствовать;
- В противном случае, все фактические параметры должны соответствовать, независимо от того, заданы ли фактические параметры явно или по умолчанию.
Правила сопоставления фактических параметров между фактическим экземпляром и формальным пакетом следующие:
- Для формального объекта с режимом in, фактические значения совпадают, если они являются статическими выражениями с одинаковым значением, или если они статически обозначают ту же константу, или если они оба являются литералом null.
- Для формального подтипа, фактические значения совпадают, если они статически обозначают совпадающие подтипы.
- Для других типов формальных параметров, фактические значения совпадают, если они статически обозначают тот же сущность.
Для целей сопоставления любой фактический параметр, являющийся именем формального объекта с режимом in, заменяется фактическим выражением формального объекта (рекурсивно).
Статическая семантика
formal_package_declaration объявляет формальный обобщенный пакет.
Видимая часть формального пакета включает первый список basic_declarative_items из package_specification. Кроме того, для каждого фактического параметра, который не требует соответствия, копия объявления соответствующего формального параметра шаблона включается в видимую часть формального пакета. Если скопированное объявление предназначено для формального типа, копии неявных объявлений примитивных подпрограмм формального типа также включаются в видимую часть формального пакета.
Для целей сопоставления, если фактический экземпляр A сам является формальным пакетом, то фактические параметры A — это те, которые заданы явно или неявно в formal_package_actual_part для A, плюс для тех, что не заданы, копии формальных параметров шаблона, включённые в видимую часть A.
Примеры
Пример обобщённого пакета с формальными параметрами пакета:
with Ada.Containers.Ordered_Maps; -- см. A.18.6
generic
with package Mapping_1 is new Ada.Containers.Ordered_Maps(<>);
with package Mapping_2 is new Ada.Containers.Ordered_Maps
(Key_Type => Mapping_1.Element_Type,
others => <>);
package Ordered_Join is
-- Предоставьте "объединение" между двумя отображениями
generic
with package Mapping_1 is new Ada.Containers.Ordered_Maps(<>);
with package Mapping_2 is new Ada.Containers.Ordered_Maps
(Key_Type => Mapping_1.Element_Type,
others => <>);
package Ordered_Join is
-- Предоставьте "объединение" между двумя отображениями
subtype Key_Type is Mapping_1.Key_Type;
subtype Element_Type is Mapping_2.Element_Type;
subtype Element_Type is Mapping_2.Element_Type;
function Lookup(Key : Key_Type) return Element_Type;
...
end Ordered_Join;
end Ordered_Join;
Пример инстанцирования пакета с формальными пакетами:
with Ada.Containers.Ordered_Maps;
package Symbol_Package is
package Symbol_Package is
type String_Id is ...
type Symbol_Info is ...
package String_Table is new Ada.Containers.Ordered_Maps
(Key_Type => String,
Element_Type => String_Id);
(Key_Type => String,
Element_Type => String_Id);
package Symbol_Table is new Ada.Containers.Ordered_Maps
(Key_Type => String_Id,
Element_Type => Symbol_Info);
(Key_Type => String_Id,
Element_Type => Symbol_Info);
package String_Info is new Ordered_Join(Mapping_1 => String_Table,
Mapping_2 => Symbol_Table);
Mapping_2 => Symbol_Table);
Apple_Info : constant Symbol_Info := String_Info.Lookup("Apple");
end Symbol_Package;