Generics 对于具有泛型成员的私有记录类型,是否可以重载=运算符?
我正在尝试重载泛型链表类的相等运算符。以下是相关代码: list.ads:Generics 对于具有泛型成员的私有记录类型,是否可以重载=运算符?,generics,operator-overloading,ada,Generics,Operator Overloading,Ada,我正在尝试重载泛型链表类的相等运算符。以下是相关代码: list.ads: 列表1.adb: main.adb: 这是我在主体部分最后一行的错误: operator for private type "List_Type" defined at list.ads:X, instance at line X is not directly visible 有没有办法让它看到“=”函数?如果我使用Int\u List.“=”(L1,L2),或者如果我将use Int\u List放在Main
列表1.adb:
main.adb:
这是我在主体部分最后一行的错误:
operator for private type "List_Type" defined at list.ads:X, instance at line X is not directly visible
有没有办法让它看到“=”函数?如果我使用Int\u List.“=”(L1,L2)
,或者如果我将use Int\u List
放在Main主体之前,它就可以工作了,但是第一种类型违背了操作符重载的目的,第二种类型允许从Main中无条件地访问所有列表函数。是的,您可以使用带有私有类型泛型参数的“=”,但是,我建议将“=”函数与私有类型一起传递,但默认为可见类型,正如带有函数的所示
另外请注意,在比较元素
时,必须比较值,而不是整个记录。(请参见带有元素参数的“=”的定义;它作为Ada 2012的表达式函数之一位于专用部分。)
Test\u 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.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;
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
是的,您可以将“=”与私有类型泛型参数一起使用,但是我建议将“=”函数与私有类型一起传递,但默认为可见类型,正如带函数的所示
另外请注意,在比较元素
时,必须比较值,而不是整个记录。(请参见带有元素参数的“=”的定义;它作为Ada 2012的表达式函数之一位于专用部分。)
Test\u 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.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;
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
在Main
中,在
package Int_Lists is new List (Integer);
你可以写
use type Int_Lists.List_Type;
或
就个人而言,我会选择使用type
。这就是它的用途。在Main
之后
package Int_Lists is new List (Integer);
你可以写
use type Int_Lists.List_Type;
或
就个人而言,我会选择使用type
。这就是它的用途。刚刚尝试过(第一个代码块在.ads文件中,第二个代码块在.adb文件中),它仍然给我相同的错误。好的,让我启动编译器,看看我能做什么。注意使用J
。。。您也可以使用类型J.List\u type
。谢谢,但我试图避免使用Use
语句,因为如果一个过程中存在多个Test\u List包的实例化,则仍然必须限定“=”函数。不过,在深入研究之后,我想我可能要求编译器有太多的魔力了。。。您是否尝试过使用type
?因为在我用J
为Image[在示例中]的调用添加前缀后,它工作得非常好。刚刚尝试过(第一个代码块在.ads文件中,第二个代码块在.adb文件中),它仍然会给我同样的错误。好的,让我启动编译器,看看我能做什么。注意使用J
。。。您也可以使用类型J.List\u type
。谢谢,但我试图避免使用Use
语句,因为如果一个过程中存在多个Test\u List包的实例化,则仍然必须限定“=”函数。不过,在深入研究之后,我想我可能要求编译器有太多的魔力了。。。您是否尝试过使用type
?因为在我用J
为Image[在本例中]的调用加上前缀后,它可以完美地工作。