相互依赖的类型声明和Ada.Containers

相互依赖的类型声明和Ada.Containers,ada,recursive-datastructures,Ada,Recursive Datastructures,在“盒式类型”(对于解释器)的实现中,我最初在子包中有向量,并使用System.Access_到_地址_的转换来根据需要从System.Address到Vector_Ptr进行转换,以避免循环依赖性中看似无法克服的问题。(至少,没有使用limited with every对我起到了作用。)它起了作用,但看起来像是一个讨厌的黑客。所以我决定将容器类型放入主包类型中。Boxed。现在GNAT抱怨“第12行定义的不完整类型“Vector”的可见部分没有声明” 有办法解决这个问题吗?还是我应该回到我讨厌

在“盒式类型”(对于解释器)的实现中,我最初在子包中有向量,并使用System.Access_到_地址_的转换来根据需要从System.Address到Vector_Ptr进行转换,以避免循环依赖性中看似无法克服的问题。(至少,没有使用limited with every对我起到了作用。)它起了作用,但看起来像是一个讨厌的黑客。所以我决定将容器类型放入主包类型中。Boxed。现在GNAT抱怨“第12行定义的不完整类型“Vector”的可见部分没有声明”

有办法解决这个问题吗?还是我应该回到我讨厌的黑客

Ada 2005使用GNAT 4.6和标志-gnat05

with Interfaces; use Interfaces;
with Ada.Strings.Wide_Unbounded; use Ada.Strings.Wide_Unbounded;
with Ada.Containers.Vectors;
with Green_Tasks; use Green_Tasks;

package Types.Boxed is

   type Type_T is (T_Null, T_Unsigned_64, T_String, T_Boolean,
                   T_Green_Task, T_Vector);

   type String_Ptr is access all Unbounded_Wide_String;
   type Vector;
   type Vector_Ptr is access all Vector;

     type Item (IType : Type_T := T_Null) is record
        case IType is
        when T_Null        => null;
        when T_Unsigned_64 => Value_Unsigned_64  : Unsigned_64;
        when T_String      => Value_String       : String_Ptr;
        when T_Boolean     => Value_Boolean      : Boolean;
        when T_Green_Task  => Value_Green_Task   : Green_Task_Ptr;
        when T_Vector      => Value_Vector       : Vector_Ptr;
        end case;
   end record;

   procedure Free (Datum : in out Item);
   procedure Box (Datum : out Item; Value : in Unsigned_64);
   function Unbox (Datum : Item) return Unsigned_64;
   procedure Box (Datum : out Item; Value : String_Ptr);
   function Unbox (Datum : Item) return String_Ptr;
   procedure Box (Datum : out Item; Value : in Boolean);
   function Unbox (Datum : Item) return Boolean;
   procedure Box (Datum : out Item; Value : in Green_Task_Ptr);
   function Unbox (Datum : Item) return Green_Task_Ptr;
   function Get_Boxed_Type (Datum : Item) return Type_T;

   -- vectors
    package Item_Vectors is new Ada.Containers.Vectors
     ( Index_Type   => Natural,
      Element_Type => Item
     );
   use Item_Vectors;


   function Vector_New (Size_Hint : Positive) return Item;
   function Unbox (Datum : Item) return Vector_Ptr;
   procedure Vector_Free (V : in out Vector_Ptr);
   function Vector_Copy (V : Vector_Ptr) return Item;

   pragma Inline (Box);
   pragma Inline (Unbox);
   pragma Pure_Function (Unbox);
   pragma Pure_Function (Get_Boxed_Type);


end Types.Boxed;

我仔细研究了一下,发现我可以通过制作元素类型
Item\u Ptr
Item\u向量来编译它:

type Item (<>);
type Item_Ptr is access all Item;

package Item_Vectors is new Ada.Containers.Vectors
 ( Index_Type   => Natural,
   Element_Type => Item_Ptr
  );
subtype Vector is Item_Vectors.Vector;
type Vector_Ptr is access all Vector;

type Item (IType : Type_T := T_Null) is record
   case IType is
      when T_Null        => null;
      when T_Unsigned_64 => Value_Unsigned_64  : Unsigned_64;
      when T_String      => Value_String       : String_Ptr;
      when T_Boolean     => Value_Boolean      : Boolean;
      when T_Vector      => Value_Vector       : Vector_Ptr;
     end case;
end record;
类型项();
类型项_Ptr为访问所有项;
包装项目_Vectors是新的Ada.Containers.Vectors
(索引类型=>自然,
元素类型=>项目类型
);
子类型向量为Item_Vectors.Vector;
类型Vector_Ptr是访问所有向量;
类型项(IType:type\U T:=T\U Null)为记录
案例类型为
当T_Null=>Null时;
当T_Unsigned_64=>Value_Unsigned_64时:Unsigned_64;
当T_String=>Value_String:String_Ptr;
当T_Boolean=>Value_Boolean时:Boolean;
当T_Vector=>Value_Vector:Vector_Ptr;
终例;
结束记录;
(我删除了绿色任务,希望与您的问题无关)


我很感兴趣地看到,如果不完整的声明是在私有部分,那么完整的声明只能推迟到正文中。

我对此进行了研究,发现我可以通过制作元素类型
Item\u Ptr
Item\u Vectors
来编译它:

type Item (<>);
type Item_Ptr is access all Item;

package Item_Vectors is new Ada.Containers.Vectors
 ( Index_Type   => Natural,
   Element_Type => Item_Ptr
  );
subtype Vector is Item_Vectors.Vector;
type Vector_Ptr is access all Vector;

type Item (IType : Type_T := T_Null) is record
   case IType is
      when T_Null        => null;
      when T_Unsigned_64 => Value_Unsigned_64  : Unsigned_64;
      when T_String      => Value_String       : String_Ptr;
      when T_Boolean     => Value_Boolean      : Boolean;
      when T_Vector      => Value_Vector       : Vector_Ptr;
     end case;
end record;
类型项();
类型项_Ptr为访问所有项;
包装项目_Vectors是新的Ada.Containers.Vectors
(索引类型=>自然,
元素类型=>项目类型
);
子类型向量为Item_Vectors.Vector;
类型Vector_Ptr是访问所有向量;
类型项(IType:type\U T:=T\U Null)为记录
案例类型为
当T_Null=>Null时;
当T_Unsigned_64=>Value_Unsigned_64时:Unsigned_64;
当T_String=>Value_String:String_Ptr;
当T_Boolean=>Value_Boolean时:Boolean;
当T_Vector=>Value_Vector:Vector_Ptr;
终例;
结束记录;
(我删除了绿色任务,希望与您的问题无关)


我很感兴趣地从中看到,如果不完整的声明在私有部分,则完整的声明只能推迟到正文中。

好的,我假设您在实例化
项向量
并说
使用项向量
时,
Vector
输入
Item\u Vectors
将完成前面编写的不完整的
Vector

没有。当您说
use P
时,这意味着
P
中定义的所有名称现在都可以直接看到,因此如果
P
声明类型
T
,您可以说
T
,而不是说
P.T
但符号仍然属于P。它们不会成为包含
use
的包的“一部分”。因此,例如,
使用项_向量
表示您可以说
空光标
,而不是
项向量。空光标
。但是将有而不是
一个
Types.Boxed.Empty\u光标
。该名称仍然属于
项向量

这意味着当您在
类型中有一个不完整的
向量
类型时,需要在
类型中有一个完成
Item\u Vectors
中的
Vector
类型不会成为该类型的补全,而
使用
也没有帮助

不幸的是,Ada不允许您使用“类型重命名”或
子类型来完成类型。我能想到的最好的选择是

type Vector is new Item_Vectors.Vector with null record;
请注意,这会导致
项_Vector
中的所有操作被继承到
Vector
。所以这可能对你有用。但可能会有一些意想不到的问题。但我想不出更好的解决办法


编辑:Simon似乎有一个很好的解决方案。

好吧,我假设您在实例化
项目向量
并说
使用项目向量
时认为,
向量
输入
项目向量
将是您之前编写的不完整
向量
的完成

没有。当您说
use P
时,这意味着
P
中定义的所有名称现在都可以直接看到,因此如果
P
声明类型
T
,您可以说
T
,而不是说
P.T
但符号仍然属于P。它们不会成为包含
use
的包的“一部分”。因此,例如,
使用项_向量
表示您可以说
空光标
,而不是
项向量。空光标
。但是将有而不是
一个
Types.Boxed.Empty\u光标
。该名称仍然属于
项向量

这意味着当您在
类型中有一个不完整的
向量
类型时,需要在
类型中有一个完成
Item\u Vectors
中的
Vector
类型不会成为该类型的补全,而
使用
也没有帮助

不幸的是,Ada不允许您使用“类型重命名”或
子类型来完成类型。我能想到的最好的选择是

type Vector is new Item_Vectors.Vector with null record;
请注意,这会导致
Item_Vector
中的所有操作为继承