我正在尝试将通用链接列表类的相等运算符超载。这是相关代码:
list.ads:
generic
type Element_Value_Type is private;
package List is
type List_Type is private;
type Element is private;
type Element_Ptr is private;
function "=" (L, R : List_Type) return Boolean;
-- Other linked list function declarations --
private
type Element is
record
Value : Element_Value_Type;
Next : Element_Ptr;
Prev : Element_Ptr;
end record;
type Element_Ptr is access Element;
type List_Type is
record
Length : Integer := 0;
Head : Element_Ptr := null;
Tail : Element_Ptr := null;
end record;
end List;
list.adb:
package body List is
function "=" (Left, Right : List_Type) return Boolean is
begin
-- Code for equality checking --
end "=";
-- Other function implementations --
end List;
main.Adb:
with Text_IO;
with List;
use Ada;
procedure Main is
package Int_Lists is new List (Integer);
procedure Print_List (List : Int_Lists.List_Type) is
begin
-- code to print the contents of a list --
end
L1, L2 : Int_Lists.List_Type;
begin
Int_Lists.Append (L1, 1);
Int_Lists.Append (L2, 1);
Int_Lists.Append (L1, 2);
Int_Lists.Append (L2, 2);
Text_IO.Put_Line (Item => Boolean'Image (L1 = L2));
end Main;
这是我在主体的最后一行中遇到的错误:
operator for private type "List_Type" defined at list.ads:X, instance at line X is not directly visible
有什么方法可以让它看到" ="函数?如果我执行Int_Lists."=" (L1, L2)
,或者如果我将use Int_Lists
放在Main主体之前,则有效,但是第一个击败了操作员过载的目的,而第二种允许从MAIN内部进行所有列表功能的无限访问。
在 Main
中,
package Int_Lists is new List (Integer);
您可以写
use type Int_Lists.List_Type;
或
function "=" (L, R : Int_Lists.List_Type) return Boolean
renames Int_Lists."=";
就个人而言,我要去use type
。这就是它的目的。
是的,您可以使用私有类型的通用参数使用" =",但是我建议我与私有类型一起传递" ="函数,但默认为可见的函数,with function … is <>
表示。
另外,,请注意,在比较Element
时,您必须比较值,而不是整个记录。(请参阅具有元素参数的" ="的定义;它是ADA 2012表达式功能之一。)
Test_List.ads
generic
type Element_Value_Type is private;
with function "=" (Left, Right : Element_Value_Type) Return Boolean is <>;
-- Image only for debugging.
with function Image( Value : Element_Value_Type ) Return String;
package Test_List is
type List_Type is private;
type Element is private;
type Element_Ptr is private;
function "=" (L, R : List_Type) return Boolean;
Procedure Append(List : in out List_Type; Item : Element_Value_Type);
function Image( List : List_Type ) Return String;
private
type Element is
record
Value : Element_Value_Type;
Next : Element_Ptr;
Prev : Element_Ptr;
end record;
function "=" (Left, Right : Element ) Return boolean is
( Left.Value = Right.Value );
type Element_Ptr is access Element;
type List_Type is
record
Length : Integer := 0;
Head : Element_Ptr := null;
Tail : Element_Ptr := null;
end record;
end Test_List;
Test_List.adb
Package Body Test_List is
function "=" (L, R : List_Type) return Boolean is
begin
Return Result : Boolean:= L.Length = R.Length do
-- We only need to check if lengths are equal.
if not Result then Return; end if;
declare
SubType NN_Element_Ptr is Not Null Element_Ptr;
L_Cursor : NN_Element_Ptr:= L.Head;
R_Cursor : NN_Element_Ptr:= R.Head;
begin
loop
if L_Cursor.Value /= R_Cursor.Value then
Result:= False;
Return;
end if;
Exit when L_Cursor = L.Tail;
L_Cursor:= L_Cursor.Next;
R_Cursor:= R_Cursor.Next;
end loop;
end;
exception
when Constraint_Error =>
-- Handle empty lists.
Result:= L.Tail = R.Tail;
End return;
end "=";
Procedure Append(List : in out List_Type; Item : Element_Value_Type) is
begin
List.Tail:= new Element'(
Value => Item,
Next => null,
Prev => List.Tail
);
-- If this is the inital element we link head to ie, if not we need
-- to link the previous tail's next-pointer to the current tail.
if List.Length = 0 then
List.Head := List.Tail;
else
List.Tail.Prev.Next:= List.Tail;
end if;
List.Length:= List.Length + 1;
end Append;
Function Image( List : List_Type ) Return String is
Separator : Constant String := ", ";
Function Image( Item : Element_Ptr ) Return String is
begin
if Item = Null then
Return "";
else
Return Image(Item.Value) & Separator & Image(Item.Next);
end if;
end Image;
Temp : String:= Image( List.Head );
begin
Return '(' & Temp(temp'First..temp'Last-Separator'Length) & ')';
end Image;
End Test_List;
test.adb
With
Test_List,
Ada.Text_IO;
Procedure Test is
Package J is new Test_List( Integer, Image => Integer'Image );
L1, L2 : J.List_Type;
Use J;
Begin
Ada.Text_IO.Put_Line( Image(L1) );
J.Append (L1, 1);
J.Append (L2, 1);
J.Append (L1, 2);
J.Append (L2, 2);
J.Append (L1, 3);
J.Append (L2, 3);
Ada.Text_IO.Put_Line( Image(L1) );
Ada.Text_IO.Put_Line( "List equality: " & Boolean'(L1 = L2)'Img );
J.Append (L2, 1);
J.Append (L1, 2);
Ada.Text_IO.Put_Line( "List equality: " & Boolean'(L1 = L2)'Img );
End Test;
输出是:
()
( 1, 2, 3)
List equality: TRUE
List equality: FALSE