Скажем, у меня есть формальный тип массива и функция для поиска индекса данного элемента в этом массиве, например:
generic
type T is private;
type T_index is (<>);
type T_array is array(T_index range <>) of T;
function FindIndexGeneric(array: T_array; element: T; elementFound: out Boolean) return T_index;
Создание экземпляра для неограниченного массива, такого как строка, отлично работает:
function FindIndexString is new FindIndexGeneric
(T=>Character, T_index=>Positive, T_array=>String);
Но то же самое не работает, когда у меня есть ограниченный массив:
type userIDIndex is Integer range 1..6;
type userID is array(userIDIndex) of Character;
function FindIndexUserID is new FindIndexGeneric
(T=>Character, T_index=>userIDIndex, T_array=>userID);
-- error: expect unconstrained array in instantiation of "T_array"
Я могу заставить массивы с ограничениями работать, изменив строку объявления формального массива на:
type T_array is array(T_index) of T;
но тогда я не могу создавать неограниченные массивы с этим.
Учитывая, что основная логика в моих функциях массива (FindIndexGeneric
) одинакова, я не хочу создавать несколько ее версий, по одной для массивов с ограничениями и без ограничений.
Есть ли способ заставить общую функцию работать как с ограниченными, так и с неограниченными массивами?
Я не думаю, что есть способ создать универсальный экземпляр как с ограниченным, так и с неограниченным массивом, но есть своего рода обходной путь: вы можете создать экземпляр с неограниченным массивом и определить ограниченный подтип неограниченного типа массива, и затем вы можете вызвать созданную универсальную функцию с параметром ограниченного подтипа. Так:
generic
type T is private;
type T_index is (<>);
type T_array is array (T_index range <>) of T;
...
type userIDIndex is Integer range 1..6;
type userIDUnconstrained is
array (userIDIndex range <>) of Character;
subtype userID is userIDUnconstrained (userIDIndex);
function FindIndexUserID is new FindIndexGeneric
(T => Character,
T_index => userIDIndex,
T_array => userIDUnconstrained);
Затем вы можете вызвать FindIndexUserID с параметром ограниченного (под)типа userID. Однако обратите внимание, что в теле дженерика вы должны пройти по параметру массива, перебирая диапазон его индексов (arry'Range), а не весь T_index.
Ваша логика идет в ограниченном варианте. Неограниченная версия объявляет соответствующий ограниченный подтип, создает с ним экземпляр ограниченной версии и вызывает ограниченный экземпляр.