Ada:泛型,不完整类型和自引用结构的困难

Meh*_*ada 0 generics packages ada package

在Ada中这很简单:

type ITEM_RECORD;
type ITEM_ACCESS is access ITEM_RECORD;
type ITEM_RECORD Is
record
   ITEM: item_type;
   Next: item_access;
   Pred: item_access;
end record;
Run Code Online (Sandbox Code Playgroud)

容易,对吗?现在,如果我想让ITEM_ACCESS成为通用包中声明的智能/安全指针,该怎么办?我直觉地这样做,只要它有效:

type ITEM_access;
type Item_Record is record
  Item : Item_Type;
  Next : Item_Access;
  Pred : Item_Access;
end record;
type pointers_on_record is access Item_record;
package pointers_p is new pointers(Item_Record, pointers_on_record);
type item_access is new pointers_p.Pointer_Type;
Run Code Online (Sandbox Code Playgroud)

通用的规格如下:

generic
   type Item_Type(<>) is limited private;
   type Access_Type is access Item_Type;
package Pointers is
   type Pointer_Type is private;
Run Code Online (Sandbox Code Playgroud)

我还没想出怎么做.

谢谢 !

fly*_*lyx 6

由于循环依赖性,您无法创建要创建的结构.想一想:

通用包定义了一个指针.Pointer_Type(可能)的结构和实现取决于泛型参数Item_Type(这不一定是真的,但如果不是,则不需要Item_Type作为通用参数).现在,Item_Type在你的泛型包的实例化中包含来自泛型包的两个智能指针,因此,取决于它的结构Pointer_Type.这是一个经典的鸡蛋或鸡蛋问题.

所以解决方案是改变你的类型的设计.让我给你一些指示(没有双关语):

看起来你正在实现一个双向链表.请注意,由于列表的循环特性,使用实现引用计数的智能指针是一个严重的错误.如果你的列表至少包含两个项目,那么任何东西都不会被释放,因为它们总是指向对方.因此,除非您的智能指针正在进行循环检测(根据您的规范无法实现),否则您无法按照自己的方式使用智能指针.

一个可能的解决方案是拥有智能指针Item_Type,而不是记录.您需要手动取消分配记录,但无论如何,您需要执行此操作,如上所述.

另一种解决方案是为整个列表提供一个全局引用计数器.创建一个不透明的列表类型,为列表提供访问器和迭代器子例程,分发项目的智能指针.智能指针增加和减少整个列表上的引用计数,一旦对列表的最后一次引用消失,整个列表将被释放.因此,只要存在至少一个对其中某些内容的引用,该列表就存在.此解决方案需要您自己实现引用计数,因为它专门用于列表结构.

最后,你可以使用Ada.Containers.Doubly_Linked_Lists,就像Jeffrey建议的那样.Item_Type正如我在第一个解决方案中所建议的那样,您可以将智能指针放在那里.