【问题标题】:Mutually dependent type declarations and Ada.Containers相互依赖的类型声明和 Ada.Containers
【发布时间】:2023-12-17 16:07:01
【问题描述】:

在“盒装类型”(用于解释器)的实现中,我最初在子包中有向量,并根据需要使用 System.Access_To_Address_Conversions 从 System.Address 转换为 Vector_Ptr,以避免看似无法克服的循环依赖问题。 (至少,对我来说,对每个人都没有使用限制。)它有效,但看起来像一个讨厌的黑客。所以我决定把容器类型放到主包Types.Boxed中。现在 GNAT 抱怨“第 12 行定义的不完整类型“向量”在可见部分没有声明”

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

Ada 2005 使用带有标志 -gnat05 的 GNAT 4.6

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;

【问题讨论】:

    标签: ada recursive-datastructures


    【解决方案1】:

    好的,我假设你在实例化Item_Vectors 并说use Item_Vectors 时认为Item_Vectors 中的Vector 类型将是你之前编写的不完整Vector 的完成。

    它没有。当你说use P时,意味着P中定义的所有名称现在都可以直接看到,所以如果P声明了一个类型T,你可以说T而不是P.T但这些符号仍然属于 P。 它们不会成为包含 use 的包的“一部分”。因此,例如,use Item_Vectors; 意味着您可以说Empty_Cursor 而不是Item_Vectors.Empty_Cursor。但是将不会Types.Boxed.Empty_Cursor。这个名字仍然属于Item_Vectors

    这意味着当您在Types.Boxed 中有一个不完整的Vector 类型时,需要有一个补全in Types.BoxedItem_Vectors 中的 Vector 类型不会成为类型的完成,use 对此没有帮助。

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

    type Vector is new Item_Vectors.Vector with null record;
    

    请注意,这会导致Item_Vector 中的所有操作都被Vector 继承。所以这可能对你有用。但可能会出现一些意料之外的问题。但我想不出更好的解决方案。

    编辑:看起来西蒙有一个很好的可能解决方案。

    【讨论】:

    • 扩展任何容器的问题在于返回容器类型值的函数的数量(Vector 有 7 个),因此必须重写。
    • @SimonWright 不,从 Ada 2005 开始,当类型扩展为 null 扩展时,函数不必被覆盖。
    • 哦,是的,我现在记得 my 尝试在这些行上的目的是让扩展程序具有额外的内容。哎呀。
    • 两种解决方案都有效。我选择了这个解决方案,因为我不想添加另一层间接,而在我解决了其他地方的一些歧义之后,GNAT 已经吞下了它。非常感谢你们!
    【解决方案2】:

    我玩弄了这个,发现我可以通过将Item_Vectors 元素类型为Item_Ptr 来编译它:

    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;
    

    (我删除了Green_Tasks,希望与您的问题无关)。

    我很感兴趣地从ARM 3.10.1(3) 看到,如果不完整的声明在私有部分,那么完整的声明只能推迟到正文。

    【讨论】:

      最近更新 更多