Те же правила справедливы для знаков операций и базовых операций, в частности, для формальных операций верно правило е, для локальных операций — правило з и для операций над глобальными типами — правило и. Кроме того, если в настраиваемом модуле используется предопределенная операция или базовая операция над формальным типом, то в экземпляре используется предопределенная операция, соответствующая фактическому типу, сопоставленного формальному.
Эти же правила применяются к обозначению типа и выражению (по умолчанию) из раздела формальных параметров настройки настраиваемого модуля.
При предвыполнении конкретизации настройки осуществляются следующие действия: сначала вычисляется каждое выражение, заданное в качестве явного фактического параметра настройки, и каждое выражение, входящее как составная часть в имя переменной или входа, заданное в качестве явного фактического параметра настройки; в языке не определен порядок вычисления этих выражений. Затем вычисляются выражения или имена по умолчанию для тех параметров, для которых опущены сопоставления (если они есть) параметров настройки; эти вычисления производятся в порядке следования описаний формальных параметров настройки. Наконец, пред- выполняется неявно сгенерированный экземпляр. Предвыполнение конкретизации настройки может также вызывать проверки некоторых ограничений, как описано ниже.
Рекурсивная конкретизация настройки недопустима в следующем смысле: если данный настраиваемый модуль включает конкретизацию другого настраиваемого модуля, то экземпляр, сгенерированный этой конкретизацией, не должен включать экземпляр первого настраиваемого модуля (независимо от того, генерируется ли этот экземпляр непосредственно или косвенно через промежуточную конкретизацию).
Примеры конкретизации настройки (см. 12.1):
procedure ОБМЕН is new ЗАМЕНА (ЭЛЕМ => INTEGER);
procedure ОБМЕН is new ЗАМЕНА (CHARACTER);
- совмещение идентификатора ОБМЕН
function КВАДРАТ is new ВОЗВ_В_КВАДРАТ (INTEGER);
- по умолчанию используется над INTEGER
function КВАДРАТ is new ВОЗВ_В_КВАДРАТ (ЭЛЕМЕНТ => МАТРИЦА,
= > ПРОИЗВЕДЕНИЕ_МАТРИЦ);
function КВАДРАТ is new ВОЗВ_В_КВАДРАТ (МАТРИЦА,
ПРОИЗВЕДЕНИЕ_МАТРИЦ);
- что эквивалентно предыдущему
package ЦЕЛ_ВЕКТОРЫ is new НАД_ВЕКТОРАМИ (INTEGER, ТАБЛИЦА, ”+”);
Примеры использования конкретизированных модулей
ОБМЕН (А, В);
А: = КВАДРАТ (А);
Т: ТАБЛИЦА (1. .5): = (10, 20, 30,40, 50) ;
К: INTEGER: = ЦЕЛ_ВЕКТОРЫ. СИГМА (Т) ; - -150 (см. 12.2)
use ЦЕЛ_ВЕКТОРЫ;
М: INTEGER: = СИГМА (Т) ; - - 150
Примечание. Опускать параметр настройки допускается только тогда, когда для него существует умолчание. Если использованы выражение по умолчанию или (отличные от простых) имена по умолчанию, то они вычисляются в том порядке, в котором описаны соответствующие формальные параметры настройки.
Если две совмещенные подпрограммы описаны в спецификации настраиваемого пакета и различаются только (формальным) типом параметров и результата, то существуют правильные конкретизации, для которых все вызовы этих подпрограмм вне экземпляра будут неоднозначными. Например:
generic
type A is (< >);
type В is private;
package G is
function СЛЕДУЮЩИЙ (X:A) return A;
function СЛЕДУЮЩИЙ (X:B) return В;
end;
package P is new G (A => BOOLEAN, В => BOOLEAN);
- все вызовы P. СЛЕДУЮЩИЙ неоднозначны.
П p а в и л а сопоставления для формальных объектов
Формальному параметру настройки вида in данного типа сопоставляется выражение этого же типа. Если настраиваемый модуль имеет формальный объект настройки вида in, то проверяется принадлежность значения выражения подтипу, заданному обозначением типа, как и для явного описания константы (см. 3.2.1). При отрицательном результате проверки этого возбуждается исключение CONSTRAINT_ERROR.
Формальному параметру настройки вида in out данного типа сопоставляется имя переменной этого же типа. Переменная не должна быть формальным параметром вида out или его подкомпонентом. Имя должно обозначать такую переменную, для которой допустимо переименование (см. 8.5).
Примечание. Тип фактического параметра настройки вида in не должен быть лимитируемым типом. Ограничения формального параметра настройки вида in out являются ограничениями соответствующего фактического параметра настройки (см. 12.1.1).
П р а в и л а сопоставления для формальных личных типов
Формальный личный тип настройки сопоставляется с типом или подтипом (фактическим подтипом), удовлетворяющим следующим условиям:
Если формальный тип не является лимитируемым, то фактический тип не должен быть лимитируемым. (С другой стороны, если формальный тип является лимитируемым, то соответствующий фактический тип может быть лимитируемым и нелимитируемым.)
Если формальный тип имеет раздел дискриминантов, то фактический тип должен быть типом с таким же числом дискриминантов; тип дискриминанта в данной позиции в разделе дискриминантов фактического типа должен совпадать с типом дискриминанта в той же позиции раздела дискриминантов формального типа; фактический подтип должен быть неограниченным. (С другой стороны, если формальный тип на имеет дискриминантов, для фактического типа дискриминанты допустимы.)
Ниже рассматривается вхождение имени формального типа в том месте, где оно использовано как указание неограниченного подтипа. Фактический подтип не должен быть неограниченным индексируемым типом или неограниченным типом с дискриминантами, если любое вхождение находится на месте, где для индексируемого типа или типа с дискриминантами требуется либо ограничение, либо выражения по умолчанию для дискриминантов (см. 3.6.1 и 3.7.2). Такое же требование предъявляется ко всем вхождениям имени подтипа формального типа, а также к вхождениям имени любого типа или подтипа, производных (непосредственно или косвенно) от этого формального типа.
Если настраиваемый модуль имеет формальный личный тип с дискриминантами, то при предвыполнении соответствующей конкретизации настройки проверяется совпадение подтипа каждого дискриминанта фактического типа и подтипа соответствующего дискриминанта формального типа. При несовпадении таких подтипов возбуждается исключение CONSTRAINT-ERROR.
П р а в и л а сопоставления для формальных скалярных типов
Формальному типу настройки, определенному символами (< >), сопоставляется любой дискретный подтип (т. е. любой перечислимый или целый подтип). Формальному типу настройки, определенному символами range О, сопоставляется любой целый подтип. Формальному типу настройки, определенному символами digits < >, сопоставляется любой плавающий подтип. Формальному типу настройки, определенному символами delta < >, сопоставляется любой фиксированный подтип. Никакие другие сопоставления для этих формальных типов настройки невозможны.
П р а в и л а сопоставления для формальных индексируемых типов
Формальному индексируемому типу сопоставляется фактический индексируемый подтип, удовлетворяющий следующим условиям.
Формальный и фактический индексируемые типы должны иметь одинаковые размерности; формальный тип и фактический подтип должны быть либо оба ограниченными, либо оба неограниченными.
Для каждой позиции индекса тип индекса фактического индексируемого типа должен совпадать с типом индекса формального индексируемого типа.
Типы компонентов фактического и формального индексируемых типов должны быть одинаковыми. Если тип компонента отличен от скалярного, то подтипы компонентов фактического и формального индексируемых типов должны быть либо оба ограниченными, либо оба неограниченными.
Если настраиваемый модуль имеет формальный индексируемый тип, то при предвыполнении соответствующей конкретизации проверяется совпадение ограничений (если они есть) на тип компонента фактического индексируемого типа с ограничениями для формального индексируемого типа; для любой данной позиции индекса индексируемых подтипов или дискретных диапазонов проверяется совпадение границ.
При несовпадениях возбуждается исключение CONSTRAINT-ERROR. Пример:
- задание настраиваемого пакета
generic
type ЭЛЕМЕНТ is private;
type ИНДЕКС is К >);
type ВЕКТОР is array (ИНДЕКС range < >) of ЭЛЕМЕНТ;
type ТАБЛИЦА is array (ИНДЕКС) of ЭЛЕМЕНТ;
package P is
end;
- даны типы
type СМЕСЬ is array (ЦВЕТ range < >) of BOOLEAN;
type ВЕРСИЯ is array (ЦВЕТ) of BOOLEAN;
- теперь тип СМЕСЬ может быть сопоставлен типу ВЕКТОР, а ВЕРСИЯ - типу - - ТАБЛИЦА
package R is new Р (ЭЛЕМЕНТ => BOOLEAN, ИНДЕКС => ЦВЕТ, ВЕКТОГ=> СМЕСЬ, ТАБЛИЦА => ВЕРСИЯ);
- Заметим, что СМЕСЬ не может быть сопоставлена с ТАБЛИЦА, а ВЕРСИЯ - с - - ВЕКТОР.
Примечание. Если тип любого индекса или тип компонента формального индексируемого типа сам является формальным типом, то по приведенным правилам в экземпляре его имя обозначает соответствующий фактический подтип (см. 12.3 г).
П р а в и л а сопоставления для формальных ссылочных типов
Формальному ссылочному типу сопоставляется фактический ссылочный подтип, если тип указываемых объектов для формального и фактического типов один и тот же. Если указываемый тип отличен от скалярного, то указанные подтипы должны быть либо оба ограниченными, либо оба неограниченными .
Если настраиваемый модуль имеет формальный ссылочный тип, то при предвыполнении соответствующей конкретизации проверяется совпадение любых ограничений на указанные объекты фактического и формального ссылочных типов. При несовпадении возбуждается исключение CONSTRAINT-ERROR.
Пример:
- формальным типам настраиваемого пакета generic
type УЗЕЛ is private;
type СВЯЗЬ is access УЗЕЛ;
package P is
end;
- могут быть сопоставлены фактические типы
type МАШИНА;
type ИМЯ_МАШИНЫ is access МАШИНА;
type МАШИНА is record
ПРЕД, СЛЕД: ИМЯ_МАШИНЫ;
НОМЕР: РЕГИСТРАЦИОННЫЙ-НОМЕР;
ВЛАДЕЛЕЦ: ПЕРСОНА;
end record;
- в следующей конкретизации настройки
package R is new Р (УЗЕЛ => МАШИНА, СВЯЗЬ => ИМЯ_МАШИНЫ) ;
Примечание. Если указанный тип сам является формальным, то, в соответствии с описанными выше правилами, в экземпляре его имя обозначает соответствующий фактический подтип (см. 12.3 г).
П р а в и л а сопоставления для формальных подпрограмм
Формальной подпрограмме сопоставляются фактическая подпрограмма, литерал перечисления или вход, если они имеют один и тот же профиль типов параметров и результата (см. 6.6), при этом виды формальных и фактических параметров в одинаковых позициях должны быть одинаковыми.
Если настраиваемый модуль имеет подпрограмму по умолчанию, заданную именем, то это имя должно обозначать подпрограмму, литерал перечисления или вход, сопоставленный формальной подпрограмме (в указанном выше смысле). Вычисление имени по умолчанию производится во время предвыполнения каждой конкретизации, в которой используется это умолчание, как определено в разд. 12.3.
Если настраиваемый модуль имеет подпрограмму по умолчанию, специфицированную как бокс, то соответствующий фактический параметр может быть опущен, если подпрограмма, литерал перечисления или вход, сопоставляемые формальной подпрограмме, имеют то же обозначение, что и формальная подпрограмма, и непосредственно на месте конкретизации должна быть видима единственная такая подпрограмма, или литерал перечисления, или вход.
Пример:
- дана спецификация настраиваемой функции
generic
type ЭЛЕМЕНТ is private;
with function (А, В: ЭЛЕМЕНТ) return ЭЛЕМЕНТ is < >;
function ВОЗВ_В_КВАДРАТ (X: ЭЛЕМЕНТ) return ЭЛЕМЕНТ;
- и функция
function ПРОИЗВЕДЕНИЕ_МАТРИЦ (А, В: МАТРИЦА) return МАТРИЦА;
- возможна следующая конкретизация
function КВАДРАТ os new ВОЗВ_В_КВАДРАТ (МАТРИЦА,
ПРОИЗВЕДЕНИЕ_МАТРИЦ);
- следующие конкретизации эквивалентны
function КВАДРАТ is new ВОЗВ_В_КВАДРАТ (ЭЛЕМЕНТ => INTEGER,
=> ”*”);
function КВАДРАТ is new ВОЗВ_В_КВАДРАТ (INTEGER, ”*”) ;
function КВАДРАТ is new ВОЗВ_В_КВАДРАТ (INTEGER);
Примечание. Правила сопоставления для формальных подпрограмм устанавливают требования, которые подобны требованиям, применяемым к описаниям переименования подпрограмм (см. 8.5). В частности, не требуется совпадения имен соответствующих параметров формальной и фактической подпрограмм; аналогично, для таких параметров не обязательно соответствие выражений по умолчанию.
Формальной подпрограмме сопоставляется атрибут типа, если этот атрибут - функция с сопоставимой спецификацией. Литерал перечисления данного типа сопоставляется с формальной функцией без параметров и результатом данного типа.
12.4. Пример настраиваемого пакета
В следующем примере использован настраиваемый пакет для одной из возможных организаций стеков. Размер каждого стека и тип его элементов являются параметрами настройки.
generic
РАЗМЕР: POSITIVE;
type ЭЛЕМЕНТ is private;
package СТЕК is
procedure B_CTEK (E: in ЭЛЕМЕНТ) ;
procedure ИЗ-СТЕКА (E: out ЭЛЕМЕНТ);
ПЕРЕПОЛНЕНИЕ, ПУСТОТА: exception;
end СТЕК;
package body СТЕК is
type ТАБЛИЦА is array (POSITIVE range < >) of ЭЛЕМЕНТ;
МЕСТО: ТАБЛИЦА (1. .РАЗМЕР);
ИНДЕКС: NATURAL: = 0;
procedure В_СТЕК (Е: in ЭЛЕМЕНТ) is
begin
if ИНДЕКС > = РАЗМЕР then
raise ПЕРЕПОЛНЕНИЕ;
end if;
ИНДЕКС: = ИНДЕКС + 1;
МЕСТО (ИНДЕКС): = Е;
end В_СТЕК;
procedure ИЗ _СТЕКА (Е: out ЭЛЕМЕНТ) is
begin
if ИНДЕКС = 0 then
raise ПУСТОТА;
end if;
E: = МЕСТО (ИНДЕКС);
ИНДЕКС: = ИНДЕКС - 1;
end ИЗ_СТЕКА;
end СТЕК;
Экземпляры настраиваемого пакета могут быть получены так:
package СТЕК_ЦЕЛ is new СТЕК (РАЗМЕР => 200, ЭЛЕМЕНТ => INTEGER);
package СТЕК_ЛОГ is new СТЕК (100, BOOLEAN):
После этого могут быть вызваны процедуры конкретизированных пакетов :