1

我正在尝试为通用链表类重载相等运算符。以下是相关代码:

列表广告:

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;

列表.adb:

package body List is
    function "=" (Left, Right : List_Type) return Boolean is
    begin
        --  Code for equality checking  --
    end "=";

    --  Other function implementations  --
end List;

主.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;

这是我在 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_ListsMain 的主体之前,它就可以工作,但是第一种破坏了运算符重载的目的,而第二种允许从 Main 中无限制地访问所有 List 函数。

4

2 回答 2

3

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。这就是它的用途。

于 2012-11-01T15:52:28.020 回答
2

是的,您可以将“=”与私有类型泛型参数一起使用,但是我建议将“=”函数与私有类型一起传递,但默认为可见的,如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
于 2012-10-31T23:49:35.650 回答