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

标签 generics ada dynamic-arrays

我想在描述二维离散空间的包中创建一个标记类型,其大小由运行时间决定。
(上下文:game of life 的实现)

我发现的第一种方法是通用性:

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;

但是,在为世界实现访问者时,通用性成为一个大问题:
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_Array 需要一个明确的坐标范围。
事实上,我不知道如何在标记类型中创建一个运行时选择大小的数组。
我从 herehereherehere 得到了一些想法,但在这种情况下似乎没有任何意义。

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

最佳答案

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

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

package Worlds is
   type World_Type (Size : Natural) is tagged private;
   type World is access World_Type’Class;          -- ‘’ to fix SO colour bug
private
   type World_Array is array (Positive range <>, Positive range <>) of Boolean;
   type World_Type (Size : Natural) is tagged record
      Content : World_Array (1 .. Size, 1 .. Size);
   end record;
end Worlds;

其中 World_Array 是无约束数组类型 ( ARM 3.6 ) 的一个示例。你会通过像这样的代码创建一个新世界

W : Worlds.World := new Worlds.World_Type (Size => 100);

请注意,在创建对象后,您无法更改 Size

我遗漏了 Coordinate ;并且您可能会在没有 Init 的情况下逃脱,特别是如果您为 Content 提供初始化程序:

      Content : World_Array (1 .. Size, 1 .. Size) :=
        (others => (others => False));

编辑 26.iii.15:代码正在创建一个大小为 Size + 1 x Size + 1 的数组。

关于generics - Ada:具有可变大小数组属性的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29155034/

相关文章:

c# - 由于某种原因,自定义 IComparer 实现未按预期排序

compilation - Windows 上的 gprbuild 速度慢

c - C 中的三角数组

c# - .NET 反射 - 泛型类型定义的 GetInterfaces() 结果无法与泛型文字类型成功比较

Java 通用类的可分配性

java - 如何从参数化类型方法参数中获取参数化类型类?

stream - Ada - 如何显式打包位字段记录类型?

types - 是否可以为 Protocol Buffer 中的字段定义数字范围?

c++ - 使用ArrayQueue的循环队列表示

c++ - 调试断言失败!表达式: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)