I'm trying to build a generic linked list in Ada off of a generic Node class. However, I'm unable to access types and formal parameters of my Node inside of my Linked List, despite using a with
clause and prefixing accordingly.
genericnode.ads:
generic
type item_type is private;
package GenericNode is
type Node is limited private;
type NodePtr is access Node;
procedure GetData(n : in Node; e : out item_type);
procedure GetNext(n : in Node; x : out NodePtr);
procedure SetData(n : in out Node; e : in item_type);
procedure SetNext(n : in out Node; x : in NodePtr);
private
type Node is
record
data : item_type;
next : NodePtr;
end record;
end GenericNode;
genericsll.ads:
with GenericNode;
generic
size : Positive;
type node_type is private;
package GenericSLL is
type SLL is limited private;
procedure Append(s : in out SLL; d : in GenericNode.item_type);
procedure PrintTraversal(s : in SLL);
private
type SLL is
record
head : NodePtr := null;
length : Positive := 0;
end record;
end GenericSLL;
Upon compilation, I'm told Invalid prefix in selected component "GenericNode"
and "NodePtr" is not visible
regarding genericsll.ads. Any suggestions? Thanks!
With generic packages in Ada, you need to first instantiate them. GenericNode is not a package; it is a recipe for packages, given a type item_type. Both errors are indicative of this problem; the compiler correctly states there is no such package and no such type NodePtr. ('invalid prefix in selected component GenericNode' just means I have no idea what you mean by 'GenericNode')
Where in C++, you might expect indeed to make your singly linked list parameterized on the node type, and then tell the compiler 'just grab the X and Y members of this node type, even though I haven't told you what the node type actually is yet', the Ada compiler refuses this because it leads to error-prone code, where you cannot tell what the type should satisfy (contracts in C++20 are meant to patch over this problem).
Ada does not allow this; every package must be instantiated before use, so that the parameters to each type are known. Unfortunately, this also means it is not possible to do arbitrary compile-time computation in Ada as in C++.
If you parameterize GenericSLL on item_type and instead of on node_type, it can instantiate the specific GenericNode package it needs using that item_type. Only GenericSLL needs to be modified:
with GenericNode;
generic
size : Positive;
type item_type is private;
package GenericSLL is
package LinkedList_Node is new GenericNode(item_type);
use LinkedList_Node;
type SLL is limited private;
procedure Append(s : in out SLL; d : in item_type);
procedure PrintTraversal(s : in SLL);
private
type SLL is
record
head : NodePtr := null;
length : Natural := 0; -- Positive starts at 1
end record;
end GenericSLL;