Ada:具有可变大小数组属性的对象 [英] Ada: objects with variable-sized array attribute

查看:188
本文介绍了Ada:具有可变大小数组属性的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在封装内创建一个标记类型,它描述了一个二维离散空间,其大小在运行时确定。
(上下文:执行人生游戏



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

 通用
尺寸:自然;
包世界是
类型World_Type被标记为private;
类型世界正在访问World_Type'Class;
子类型坐标为正范围1..Size;
private
类型World_Array是Boolean的坐标(Coordinate,Coordinate);
类型World_Type被标记记录
内容:World_Array;
结束记录;
结束世界;

但是,当为世界实现访问时,通用性成为一个大问题:

 与Worlds; 

包World_Visitors是
类型World_Visitor_Type被标记为private;
类型World_Visitor访问World_Visitor_Type'Class;

程序Visite(v:World_Visitor_Type;
w:in Worlds.World); - 错误:选定组件中的无效前缀Worlds
private
类型World_Visitor_Type被标记为空记录;
end World_Visitors;

GNAT无法编译,因为Worlds是一个通用包。
然后,因为我不想为每个可能的世界大小编写一个访问器,所以我尝试使用C ++方法:将大小声明为带标记类型的属性。

 包世界是
类型World_Type被标记为private;
类型世界正在访问World_Type'Class;
子类型坐标是正范围<>;

函数Init(大小:自然)return World; - 将Content属性初始化为长度数组(大小*大小)
私有
类型World_Array是布尔的数组(坐标,坐标);
类型World_Type被标记记录
内容:World_Array;
尺寸:自然;
结束记录;
结束世界;

而且,预​​计这不起作用,因为World_Array需要明确的坐标范围。
实际上,我不知道如何创建一个标记类型的运行时选择大小的数组。
我从这里得到了一些建议, a href =https://stackoverflow.com/questions/22768834/ada-packing-record-with-variable-sized-array>这里, / 1732027 / returns-a-variable-sized-matrix-from-a-function-in-ada html#4.3rel =nofollow noreferrer> here ,但在这种情况下没有任何意义。



大小的数组属性?

解决方案

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



就你的情况而言,这看起来像

 包世界是
类型World_Type(大小:Natural)被标记为private;
类型世界正在访问World_Type'Class; - ''来修正SO颜色bug
private
type World_Array是Boolean的数组(正范围<>正范围>);
类型World_Type(Size:Natural)被标记为记录
Content:World_Array(1 .. Size,1 .. Size);
结束记录;
结束世界;

其中 World_Array 无约束数组类型 ARM 3.6 )。您可以通过代码创建一个新世界,比如:

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

请注意,您无法更改大小

我省略了坐标;如果你为 Content 提供了一个初始化工具,那么你可能会在 Init> b

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

编辑过26.iii.15:代码创建一个大小<$ c $的数组c>大小+ 1 x 大小+ 1

I want to create a tagged type inside a package that describes a 2D discrete space, with a size determined in running time. (context : implementation of a game of life)

First way I found was genericity :

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;

But, when implementing a visitor for worlds, genericity become a big problem :

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 can't compile that, because Worlds is a generic package. Then, because I don't want to write a Visitor for each possible world size, I try the C++ way : declare the size as attribute in the tagged type.

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;

And, expectedly, this doesn't work, because World_Array needs an explicit range for Coordinates. In fact, I have no idea how to create a running-time-choosen sized array in a tagged type. I got some ideas from here, here, here or here, but nothing seems to make sense in this case.

How does Ada implement objects with variable-sized array attribute?

解决方案

The normal Ada way to address this problem is to use a discriminant (see ARM 3.7).

In your case, this would look something like

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;

in which World_Array is an example of an unconstrained array type (ARM 3.6). You’d create a new world by code like

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

Note that you can’t change the Size after the object has been created.

I left out Coordinate; and you may get away without Init, especially if you provide an initializer for Content:

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

Edited 26.iii.15: Code was creating an array of size Size + 1 x Size + 1.

这篇关于Ada:具有可变大小数组属性的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆