如何强制私有类型的准确索引

时间:2016-09-30 15:42:20

标签: generics compilation ada

我有一个内部使用二维数组的私有类型,每当设置该数组的元素时进行额外的处理。我的包看起来像这样:

with MyElements;
generic
    Width, Height : Positive;
package MyPackage is
    subtype MyXCoordinate is Positive range 1..Width;
    subtype MyYCoordinate is Positive range 1..height;
    type MyCoordinate is
        record
            x : MyXCoordinate;
            y : MyYCoordinate;
        end record;
    type MyType is private;
    function Create return MyType;
    function Get (this  : in MyType;
                  coord : in MyCoordinate) return MyElements.MyElementType;
    procedure Set (this    :    out MyType;
                   coord   : in     MyCoordinate;
                   element : in    MyElements.MyElementType);
private
    type MyTypeData is array (MyXCoordinate,MyYCoordinate)
      of MyElements.MyElementType;
    type MyType is 
        record
            data       : MyTypeData;
            otherstuff : ThatIsActuallyInThePackageButNotRelevant;
        end record;
end MyPackage

但是,这会强制与MyPackage接口的包是通用的,或者使用正确的参数动态实例化新的MyPackage。在执行中,这些参数很早就可以使用(它们是从一个在命令行传入的文件中读取的),但是我似乎还缺少一个可以为我做这个的语言元素。

我认为只使用未绑定的Positives作为坐标,删除泛型并允许在边界失败时生成运行时outofbounds错误,但我不禁觉得Ada必须有一些方法干净地执行此操作编译时间。

我知道我可以使用SPARK,但它对这个项目来说太过分了(这个项目是一个用Ada编写的游戏来展示它的特性)并且有点挫败了它的目的(展示了Ada的编译时错误检查!)。

我的通用实例化解决方案是否是处理此问题的正确方法,还是有更好的方法?

到目前为止,我的尝试不起作用,但感觉它们可能很接近:

type MyType is
    record
        Width,Height : Positive;
        subtype XCoordinate is Positive 1..Width;
        subtype YCoordinate is Positive 1..Height;
        data : array (XCoordinate,YCoordinate) of MyElements.MyElementType;
    end record;

使用'generator'包装来包装通用包,该包将宽度/高度作为参数传递给函数和过程,然后调用包。 (很多代码,不起作用,不会在这里浪费空间)。

1 个答案:

答案 0 :(得分:3)

看起来你需要阅读判别式,无约束数组和不确定类型。

这是一个通用软件包,可以解决您的实际问题:

generic
   type Element_Type is private;
package Dynamic_Matrix is
   type Instance (Width, Height : Positive) is tagged private;

   procedure Set (Item  : in out Instance;
                  X, Y  : in     Positive;
                  Value : in     Element_Type)
     with Pre => X <= Item.Width and Y <= Item.Height;

   function Element (Item : in     Instance;
                     X, Y : in     Positive) return Element_Type
     with Pre => X <= Item.Width and Y <= Item.Height;

private
   type Element_Matrix is array (Integer range <>,
                                 Integer range <>) of Element_Type;

   type Instance (Width, Height : Positive) is tagged
      record
         Elements : Element_Matrix (1 .. Width, 1 .. Height);
      end record;
end Dynamic_Matrix;

这是一个使用包将布尔矩阵加载到变量中的示例:

with Ada.Text_IO;

with Dynamic_Matrix;

procedure Dynamic_Matrix_Demo is
   package Positive_IO is new Ada.Text_IO.Integer_IO     (Positive);
   package Boolean_IO  is new Ada.Text_IO.Enumeration_IO (Boolean);

   package Boolean_Matrix is new Dynamic_Matrix (Element_Type => Boolean);

   Width, Height : Positive;

   use Ada.Text_IO, Positive_IO, Boolean_IO;
begin
   Get (Width);
   Get (Height);
   Skip_Line;

   declare
      Matrix : Boolean_Matrix.Instance (Width  => Width,
                                        Height => Height);
      Value  : Boolean;
   begin
      for Y in 1 .. Height loop
         for X in 1 .. Width loop
            Get (Value);
            Matrix.Set (X, Y, Value);
         end loop;
         Skip_Line;
      end loop;
   end;
end Dynamic_Matrix_Demo;