1

ジェネリック リンク リスト クラスの等価演算子をオーバーロードしようとしています。関連するコードは次のとおりです。

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;

リスト.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;

そして、これは Main の本文の最後の行に表示されるエラーです。

operator for private type "List_Type" defined at list.ads:X, instance at line X is not directly visible

「=」関数を表示させる方法はありますか? を実行するか、Main の本体の前Int_Lists."=" (L1, L2)に配置すると機能しますが、最初の 1 つは演算子のオーバーロードの目的を無効にし、2 番目の 1 つは Main 内からすべての List 関数への非修飾アクセスを許可します。use Int_Lists

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、比較するときは、レコード全体ではなく、値を比較する必要があることに注意してください。(Element パラメーターを使用した "=" の定義を参照してください。これは、Ada 2012 の式関数の 1 つとしてプライベート セクションにあります。)

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 に答える