【问题标题】:Ada Generic Linked List and Generic Package AccessAda 通用链表和通用包访问
【发布时间】:2021-04-06 09:15:26
【问题描述】:

我正在尝试在 Ada 中基于通用 Node 类构建一个通用链表。但是,尽管使用了 with 子句并相应地添加了前缀,但我无法在链接列表中访问节点的类型和形式参数。

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;

编译后,我被告知 Invalid prefix in selected component "GenericNode""NodePtr" is not visible 关于 genericsll.ads。有什么建议?谢谢!

【问题讨论】:

  • 或者,考虑multiway tree
  • 为什么不使用Ada.Containers.Doubly_Linked_Lists
  • 家庭作业可能:) 无论如何学习 Ada 是一个很好的练习
  • 不是作业,只是想在下学期之前将我的 Python ADT 知识应用到 Ada(我的一个班级使用它)。

标签: nodes ada singly-linked-list


【解决方案1】:

使用 Ada 中的通用包,您需要先实例化它们。 GenericNode 不是一个包;它是包的配方,给定类型 item_type。这两个错误都表明了这个问题;编译器正确声明没有这样的包,也没有这样的类型 NodePtr。 (“所选组件 GenericNode 中的前缀无效”只是意味着我不知道“GenericNode”是什么意思)

在 C++ 中,您可能确实希望在节点类型上参数化您的单链表,然后告诉编译器“只需获取此节点类型的 X 和 Y 成员,即使我没有告诉你什么节点类型实际上 is yet',Ada 编译器拒绝这样做,因为它会导致容易出错的代码,在这种情况下你无法判断类型应该满足什么(C++20 中的合约旨在修补这个问题)。

Ada 不允许这样做;每个包在使用前都必须实例化,以便知道每种类型的参数。不幸的是,这也意味着不可能像在 C++ 中那样在 Ada 中进行任意编译时计算。

如果您在 item_type 而不是 node_type 上参数化 GenericSLL,它可以使用该 item_type 实例化它需要的特定 GenericNode 包。只需要修改 GenericSLL:

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;

【讨论】:

  • 非常感谢!我没有考虑在我的 SLL 中实例化通用节点,因为之前在其他包中存在通用包实例化的问题。
  • 我还必须在 GenericNode 中删除我的节点类型的“私有”子句,以允许我像在 GenericSLL.Append 中那样实例化节点。
  • 在指定通用包的合同时,我使用this wiki page 上的表格。
  • 奇怪的是,您需要删除“私有”子句 - 该表显示 type X is private 将允许“任何非限制的确定类型:泛型知道可以分配给这种类型的变量并声明没有初始值的对象。所以实例化和赋值应该没问题。但是,问题可能在于您没有单独提供with function Make_Node return Node_Type 来创建具有初始值的节点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
相关资源
最近更新 更多