我有一个内部使用二维数组的私有类型,每当设置该数组的元素时进行额外的处理。我的包看起来像这样:
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'包装来包装通用包,该包将宽度/高度作为参数传递给函数和过程,然后调用包。 (很多代码,不起作用,不会在这里浪费空间)。
答案 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;