Если возможно, как бы я написал универсальную функцию Ada, работающую с двухэлементными списками любого типа элемента? Следующая спецификация функции иллюстрирует то, что я хочу, ограничивая Array_Type массивом данного element_type.
generic
type element_type is private;
type Array_Type is array (Positive range <>) of element_type;
procedure Shuffle_Array (List : in out Array_Type);
Процедура может быть создана из этого заданного element_type и строго соответствующего array_type, тогда как границымассив по-прежнему оставлен для конкретного экземпляра, чтобы варьироваться.
procedure IntArrayFoo is new Foo(element_type => Integer, array_type => Integer_Array);
Так что в случае массивов, вы можете аккуратно генерировать точно то, что может отличаться в экземплярах. Тем не менее, попытка сделать аналог с Ada.Containers.Doubly_Linked_List (T) .List приводит к проблемам.
Попытка 1 - универсальная процедура создания экземпляра пакета duply_linked_list
with Ada.Containers.Doubly_Linked_Lists;
package shufit is
generic
type element_type is private;
package int_dll is new Ada.Containers.Doubly_Linked_Lists(Element_Type => Integer);
type int_dll_type is new int_dll.List;
procedure Foo (List : in out int_dll_type);
end shufit;
Этот подход выиграл 'не работает, потому что мы не можем создать пакет в общем разделе. Даже если бы мы могли это сделать, при попытке вызвать это нам нужно сделать int_dll_type вне определения функции и все же сопоставить его - что, похоже, не работает в Ada. В C ++ я могу создать «вектор» в двух совершенно разных пространствах имен / классах, и все же они ссылаются на один и тот же тип. Но в Ada я не могу ссылаться на эквивалент в двух разных пакетах, без одного, включая другой.
Попытка 2 - универсальная процедура создания экземпляра пакета duply_linked_list
with Ada.Containers.Doubly_Linked_Lists;
generic
type element_type is private;
package shufit is
package int_dll is new Ada.Containers.Doubly_Linked_Lists(Element_Type => Integer);
type int_dll_type is new int_dll.List with null record;
procedure Foo (List : in out int_dll_type);
end shufit;
Переместив универсальный тип element_type на уровень пакета и исправив ошибку 'тип, производный от тегового типа, должен иметь расширение' с суффиксом 'with null record' в определении типа, это компилируется, но вызывающий код должен использовать это специальноопределенный тип, что означает, что если нам также нужна процедура Bar, которая работает с тем же типом, то невозможно сделать их независимо.
package shufit_pack is new shufit(element_type => Integer);
a : shufit_pack.int_dll_type;
Попытка 3 - обобщить все
Единственноевещь, о которой я могу думать, это просто бросить все дженерики в функцию, которую мы можем себе представить. На данный момент мы ничего не знаем о задействованном типе, а это значит, что нам нужно указать каждую функцию из duply_linked_list, которую нам нужно использовать.
shufit.ads:
package shufit is
generic
type element_type is private;
type list_type is private;
with function Length (List : in list_type) return Integer;
procedure Foo (List : in out list_type);
end shufit;
shufit.adb:
with Ada.Text_IO;
package body shufit is
procedure Foo (List : in out list_type) is
i : Integer := Length(List);
begin
Ada.Text_IO.Put_Line(Integer'Image(i));
end Foo;
end shufit;
использование:
package int_dll is new Ada.Containers.Doubly_Linked_Lists(Element_Type => Integer);
type int_dll_type is new int_dll.List with null record;
function IntDLL_Length (List : in int_dll_type) return Integer is
begin
return Integer(List.Length);
end IntDLL_Length;
procedure shuf_intdll is new shufit.Foo(element_type => Integer, list_type => int_dll_type, Length => IntDLL_Length);
Приятно то, что я могу заставить ту же функцию работать для массивов, что и для duply_linked_lists:
procedure Main
type IntArray is array (1..10) of Integer;
function ArrayLength (List : in IntArray) return Integer is
begin
return List'Last - List'First + 1;
end;
procedure shuf is new shufit.Foo(element_type => Integer, list_type => IntArray, Length => ArrayLength);
a : IntArray := (others => 5);
begin
shuf(a);
end Main;
Но это не то, чего я пытаюсь достичь. Я хочу что-то менее громоздкое, что работает для Dubly_linked_lists. При таком подходе вы должны переопределить каждую функцию типа списка, который вы хотите использовать. В примере, который я только что определил, Length, но обычно я хочу, чтобы функция работала на полном интерфейсе Doublely_linked_list, что означает одинаковую написание целой пачки кода, только для различных двухэлементных типов_двойных элементов.
Я просто хочунапишите в Ada эквивалент этих четырех строк C ++:
template<typename T>
void Foo(vector<T> t){
cout << t.size() << endl;
}
, которые можно использовать для векторов любого типа:
int main(){
vector<int> a = {0, 1};
Foo(a);
return 0;
}