Generics Ada:具有可变大小数组属性的对象

Generics Ada:具有可变大小数组属性的对象,generics,ada,dynamic-arrays,Generics,Ada,Dynamic Arrays,我想在描述2D离散空间的包中创建一个标记类型,其大小在运行时确定。 (背景:执行a) 我发现的第一个方法是遗传性: generic Size : Natural; package Worlds is type World_Type is tagged private; type World is access World_Type'Class; subtype Coordinate is Positive range 1..Size; private ty

我想在描述2D离散空间的包中创建一个标记类型,其大小在运行时确定。 (背景:执行a)

我发现的第一个方法是遗传性:

generic
    Size : Natural;
package Worlds is
    type World_Type is tagged private;
    type World is access World_Type'Class;
    subtype Coordinate is Positive range 1..Size;
private
    type World_Array is array (Coordinate, Coordinate) of Boolean;
    type World_Type is tagged record
            Content : World_Array;
    end record;
end Worlds;
但是,在为worlds实现访问者时,泛型成为一个大问题:

with Worlds;

package World_Visitors is
    type World_Visitor_Type is tagged private;
    type World_Visitor is access World_Visitor_Type'Class;

    procedure Visite(v : World_Visitor_Type;
                     w : in out Worlds.World); -- ERROR: invalid prefix in selected component "Worlds"
private
    type World_Visitor_Type is tagged null record;
end World_Visitors;
GNAT无法编译它,因为Worlds是一个通用包。 然后,因为我不想为每个可能的世界大小写访问者,所以我尝试C++方式:将大小声明为标记类型的属性。
package Worlds is
    type World_Type is tagged private;
    type World is access World_Type'Class;
    subtype Coordinate is Positive range <>;

    function Init(Size : Natural) return World; -- initialize Content attribute as an array of length (Size*Size)
private
    type World_Array is array (Coordinate, Coordinate) of Boolean;
    type World_Type is tagged record
            Content : World_Array;
            Size    : Natural;
    end record;
end Worlds;
包世界是
类型World\u类型标记为private;
世界类型是访问世界类型的类;
子类型坐标为正范围;
函数Init(大小:Natural)返回世界;——将内容属性初始化为长度数组(大小*大小)
私有的
类型World_Array是布尔值的数组(坐标、坐标);
类型世界\类型被标记为记录
内容:世界_阵列;
尺寸:天然;
结束记录;
世界末日;
当然,这是行不通的,因为World_数组需要一个明确的坐标范围。 事实上,我不知道如何在标记类型中创建运行时选择大小的数组。 我从或那里得到了一些想法,但在这种情况下似乎没有什么意义

Ada如何实现具有可变大小数组属性的对象?

过程访问(v:World\u Visitor\u Type;
w:在外面的世界里。世界)错误:所选组件“Worlds”中的前缀无效
这是行不通的——这是因为Worlds是一个通用的包,从类型上看,实际上没有Worlds.World这样的东西。(这意味着参数
w
的类型永远无法与实例化匹配。)

解决这一问题的一种方法是使用Worlds作为参数使
World\u访问者
通用。像这样:

通用
X:阳性;
包装温度为
子类型索引为整数范围1..X;
终端温度;
通用的
对于包K,是新的temp();
程序包温度取决于
--注意,参数I现在可以通过形式参数K依赖于temp。
函数J(I:K.索引)返回布尔值为(True);
终端温度取决于;
另一种方法是将访问者转移到Worlds包中。
另一种方法是让访问者的包成为世界之子。

解决此问题的正常Ada方法是使用判别法(请参阅)

在你的情况下,这看起来像

包世界是
类型World_type(大小:Natural)标记为private;
类型World是访问世界\u type'Class;--“”要解决如此多的颜色错误
私有的
类型World_Array是布尔值的数组(正范围,正范围);
类型世界\类型(大小:自然)标记为记录
内容:世界_数组(1.大小,1.大小);
结束记录;
世界末日;
其中,
World\u Array
是无约束数组类型()的一个示例。你可以通过这样的代码创建一个新世界

W:Worlds.World:=newworlds.World\u类型(大小=>100);
请注意,创建对象后,无法更改
大小

我遗漏了坐标
;而且您可能不需要
Init
,特别是如果您为
内容提供了一个初始值设定项

Content:World\u数组(1..Size,1..Size):=
(其他=>(其他=>错误));

编辑26.iii.15:Code正在创建一个大小为size+1xsize+1

的数组,或者将其作为一个子包。是否有办法允许重新分配内容(例如,达到更大的大小),或者有必要在新世界中操作一个世界的明确副本?使用此方案,您无法重新分配,你只能复制。您可以使
内容
成为对
世界数组
的访问,在这种情况下,您不需要鉴别器,但需要
初始化
;这将允许重新分配。您必须进行内存管理,这在理想情况下是通过从
Ada.Finalization.Controlled
(或
Limited\u Controlled
)派生
World\u Type
)并实现
Finalization