Те же правила справедливы для знаков операций и базовых операций, в частности, для формальных операций верно правило е, для локальных опе­раций — правило з и для операций над глобальными типами — правило и. Кроме того, если в настраиваемом модуле используется предопределенная операция или базовая операция над формальным типом, то в экземпляре используется предопределенная операция, соответствующая фактическому типу, сопоставленного формальному.

Эти же правила применяются к обозначению типа и выражению (по умолчанию) из раздела формальных параметров настройки настраиваемого модуля.

При предвыполнении конкретизации настройки осуществляются следу­ющие действия: сначала вычисляется каждое выражение, заданное в качест­ве явного фактического параметра настройки, и каждое выражение, входя­щее как составная часть в имя переменной или входа, заданное в качестве явного фактического параметра настройки; в языке не определен порядок вычисления этих выражений. Затем вычисляются выражения или имена по умолчанию для тех параметров, для которых опущены сопоставления (если они есть) параметров настройки; эти вычисления производятся в порядке следования описаний формальных параметров настройки. Наконец, пред- выполняется неявно сгенерированный экземпляр. Предвыполнение конкре­тизации настройки может также вызывать проверки некоторых ограниче­ний, как описано ниже.

Рекурсивная конкретизация настройки недопустима в следующем смысле: если данный настраиваемый модуль включает конкретизацию дру­гого настраиваемого модуля, то экземпляр, сгенерированный этой конкре­тизацией, не должен включать экземпляр первого настраиваемого модуля (независимо от того, генерируется ли этот экземпляр непосредственно или косвенно через промежуточную конкретизацию).

Примеры конкретизации настройки (см. 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. СЛЕДУЮЩИЙ неоднозначны.

  1. П p а в и л а сопоставления для формальных объектов

Формальному параметру настройки вида in данного типа сопоставляет­ся выражение этого же типа. Если настраиваемый модуль имеет формаль­ный объект настройки вида in, то проверяется принадлежность значения вы­ражения подтипу, заданному обозначением типа, как и для явного описания константы (см. 3.2.1). При отрицательном результате проверки этого воз­буждается исключение CONSTRAINT_ERROR.

Формальному параметру настройки вида in out данного типа сопостав­ляется имя переменной этого же типа. Переменная не должна быть фор­мальным параметром вида out или его подкомпонентом. Имя должно обо­значать такую переменную, для которой допустимо переименование (см. 8.5).

Примечание. Тип фактического параметра настройки вида in не должен быть ли­митируемым типом. Ограничения формального параметра настройки вида in out явля­ются ограничениями соответствующего фактического параметра настройки (см. 12.1.1).

  1. П р а в и л а сопоставления для формальных личных типов

Формальный личный тип настройки сопоставляется с типом или подти­пом (фактическим подтипом), удовлетворяющим следующим условиям:

  • Если формальный тип не является лимитируемым, то фактический тип не должен быть лимитируемым. (С другой стороны, если формальный тип является лимитируемым, то соответствующий фактический тип может быть лимитируемым и нелимитируемым.)

  • Если формальный тип имеет раздел дискриминантов, то фактический тип должен быть типом с таким же числом дискриминантов; тип дискри­минанта в данной позиции в разделе дискриминантов фактического типа должен совпадать с типом дискриминанта в той же позиции раздела дискри­минантов формального типа; фактический подтип должен быть неограни­ченным. (С другой стороны, если формальный тип на имеет дискриминан­тов, для фактического типа дискриминанты допустимы.)

Ниже рассматривается вхождение имени формального типа в том месте, где оно использовано как указание неограниченного подтипа. Фактический подтип не должен быть неограниченным индексируемым типом или неогра­ниченным типом с дискриминантами, если любое вхождение находится на месте, где для индексируемого типа или типа с дискриминантами требуется либо ограничение, либо выражения по умолчанию для дискриминантов (см. 3.6.1 и 3.7.2). Такое же требование предъявляется ко всем вхожде­ниям имени подтипа формального типа, а также к вхождениям имени любо­го типа или подтипа, производных (непосредственно или косвенно) от это­го формального типа.

Если настраиваемый модуль имеет формальный личный тип с дискри­минантами, то при предвыполнении соответствующей конкретизации на­стройки проверяется совпадение подтипа каждого дискриминанта факти­ческого типа и подтипа соответствующего дискриминанта формального ти­па. При несовпадении таких подтипов возбуждается исключение CONSTRAINT-ERROR.

  1. П р а в и л а сопоставления для формальных скалярных типов

Формальному типу настройки, определенному символами (< >), сопо­ставляется любой дискретный подтип (т. е. любой перечислимый или целый подтип). Формальному типу настройки, определенному символами range О, сопоставляется любой целый подтип. Формальному типу настройки, опреде­ленному символами digits < >, сопоставляется любой плавающий подтип. Формальному типу настройки, определенному символами delta < >, сопо­ставляется любой фиксированный подтип. Никакие другие сопоставления для этих формальных типов настройки невозможны.

  1. П р а в и л а сопоставления для формальных индексируемых типов

Формальному индексируемому типу сопоставляется фактический ин­дексируемый подтип, удовлетворяющий следующим условиям.

  • Формальный и фактический индексируемые типы должны иметь оди­наковые размерности; формальный тип и фактический подтип должны быть либо оба ограниченными, либо оба неограниченными.

  • Для каждой позиции индекса тип индекса фактического индексируе­мого типа должен совпадать с типом индекса формального индексируемого типа.

  • Типы компонентов фактического и формального индексируемых ти­пов должны быть одинаковыми. Если тип компонента отличен от скалярно­го, то подтипы компонентов фактического и формального индексируемых типов должны быть либо оба ограниченными, либо оба неограниченными.

Если настраиваемый модуль имеет формальный индексируемый тип, то при предвыполнении соответствующей конкретизации проверяется совпа­дение ограничений (если они есть) на тип компонента фактического индек­сируемого типа с ограничениями для формального индексируемого типа; для любой данной позиции индекса индексируемых подтипов или дискрет­ных диапазонов проверяется совпадение границ.

При несовпадениях возбуждается исключение 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 г).

  1. П р а в и л а сопоставления для формальных ссылочных типов

Формальному ссылочному типу сопоставляется фактический ссылоч­ный подтип, если тип указываемых объектов для формального и фактичес­кого типов один и тот же. Если указываемый тип отличен от скалярного, то указанные подтипы должны быть либо оба ограниченными, либо оба не­ограниченными .

Если настраиваемый модуль имеет формальный ссылочный тип, то при предвыполнении соответствующей конкретизации проверяется совпадение любых ограничений на указанные объекты фактического и формального ссылочных типов. При несовпадении возбуждается исключение 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 г).

  1. П р а в и л а сопоставления для формальных подпрограмм

Формальной подпрограмме сопоставляются фактическая подпрограм­ма, литерал перечисления или вход, если они имеют один и тот же профиль типов параметров и результата (см. 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):

После этого могут быть вызваны процедуры конкретизированных па­кетов :