0

My assignment requires the creation of a package that creates a heterogeneous (using inheritance) doubly linked list. Inserting nodes into the list is simple enough, but my issue comes in when I have to locate a node containing certain information.

PACKAGE AbstList IS
   TYPE AbstractList IS LIMITED PRIVATE;

   TYPE Node IS TAGGED PRIVATE;
   TYPE NodePtr IS ACCESS ALL Node'Class;

   PROCEDURE Init_Head(List: ACCESS AbstractList);

   PROCEDURE InsertFront(List: ACCESS AbstractList; Item: IN NodePtr; Success: OUT Boolean);

   PROCEDURE InsertRear(List: ACCESS AbstractList; Item: IN NodePtr; Success: OUT Boolean);

   FUNCTION ListSize(List: ACCESS AbstractList) RETURN Integer;

   -- The following are commented out as they are not complete in the package body

   --FUNCTION FindItem(List: ACCESS AbstractList; Value: NodePtr) RETURN NodePtr;

   --PROCEDURE Delete(List: ACCESS AbstractList; Item: NodePtr);   

   --PROCEDURE Print(List: ACCESS AbstractList);


   PRIVATE
   TYPE Node IS TAGGED RECORD
      Rlink, Llink: NodePtr;
   END RECORD;

   TYPE AbstractList IS LIMITED RECORD
      Count: Integer := 0;
      Head: NodePtr := NEW Node;
   END RECORD;

END AbstList;

One such record that I am using to insert into the list is the following:

   TYPE CarName IS (GMC, Chevy, Ford, RAM);

   TYPE Car IS NEW AbstList.Node WITH RECORD 
      NumDoors: Integer;
      Manufacturer: CarName := GMC;   -- Default manu.
   END RECORD;

So for example, how could I find a node in the list that contains a specified "Manufacturer"? It was suggested to me that I overload the "=" operator, though I am not sure how this would work given what I have. Any suggestions would be appreciated.

HoranMan
  • 1
  • 1
  • Can I ask what text you’re using that recommends keywords in UPPER CASE? The norm has been keywords in lower case, identifiers in Title_Case_With_Underscores for 20+ years – Simon Wright Mar 30 '18 at 10:38

2 Answers2

2

According to the ARM, the equality operator is predefined for the non-limited types which is the case for your Node type.

If you want a different behaviour than the default (equality of all member of your record, just override it. The function spec is in the same page, just T with your Node type (in this case Car) and write what you want

Frédéric Praca
  • 1,620
  • 15
  • 29
1

The Ada 95 Rationale Part 2 Chapter 4 says in 4.3 Class Wide Types and Operations

The predefined equality operators and the membership tests are generalized to apply to class-wide types. Like other predefined operations on such types, the implementation will depend on the particular specific type of the operands. Unlike normal dispatching operations, however, Constraint_Error is not raised if the tags of the operands do not match.

For equality, tag mismatch is treated as inequality. Only if the tags match is a dispatch then performed to the type-specific equality checking operation. This approach allows a program to safely compare two values of a class-wide tagged type for equality, without first checking that their tags match. The fact that no exception is raised in such an equality check is consistent with the other predefined relational operators, as noted in [RM83 4.5.2(12)].

So you would expect to be able to say in for example FindItem

   Current : Nodeptr := List.Head.Rlink;
begin
   ...
   if Value.all = Current.all then
      --  we’ve found a match

but the predefined equality for Car includes the Node components Llink, Rlink as well.

What’s required is an equality operation which just compares the Car components.

You might override predefined equality by saying

type Node is abstract tagged private;
function "=" (L, R : Node) return Boolean is abstract;

and then

type Car is new Abstlist.Node with record
   Numdoors: Integer;
   Manufacturer: Carname := Gmc;
end record;
overriding
function "=" (L, R : Car) return Boolean is
  (L.Manufacturer = R.Manufacturer and then L.Numdoors = R.Numdoors);

(this is Ada 2012 syntax).

Community
  • 1
  • 1
Simon Wright
  • 25,108
  • 2
  • 35
  • 62