Ada 中的变体记录数组
我想声明一个具有变体记录的元素类型的数组。 像这样的事情:
type myStruct (theType : vehicleType) is
record
...
when car => numOfWheels : Positive;
when others => null;
end record;
myArray : array (Positive range <>) of myStruct;
但在这种情况下我得到了错误。 它只允许这样:
myArray : array (1.100) of myStruct(Car); //such as
那么如何解决索引问题以及如何描述变体记录类型的数组而不给出判别性?
I want to declare an array with element-type of a variant record.
Something like this:
type myStruct (theType : vehicleType) is
record
...
when car => numOfWheels : Positive;
when others => null;
end record;
myArray : array (Positive range <>) of myStruct;
But in this case I get error.
It only allows this:
myArray : array (1.100) of myStruct(Car); //such as
So how to solve the index-problem and how to describe an array of a variant record's type without giving it's discriminant?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
上面的例子不会编译。这是一个正确的版本(为了简单起见,我将 mystruct 更改为 Integer):
其中一个错误是记录中不能有匿名数组,其次,您应该使用判别式来约束内部数组。
如上所述,这对于变长数组来说不是一个好的解决方案,因为无论如何你很可能会得到最大尺寸的数组。如果您想要具有动态确定大小的数组,您可以使用块。
它也适用于过程和函数的声明部分,其中 n 可以是传递给子程序的参数(Ada 相对于 C/C++ 的优点之一)。当然,您可以使用分配器在堆上动态分配数组。
The example above will not compile. Here is a correct version (I changed mystruct to Integer for simplicity):
One of the errors was that you cannot have anonymous arrays inside records, and second, you should use the discriminant to constrain the array inside.
As mentioned above this is not a good solution for varying-length arrays as most likely you will get a maximum sized array anyway. If you want arrays with dynamically determined sizes you can use blocks for that.
It also works in the declaration parts of procedures and functions where n can be a parameter passed to the subprogram (one of the advantages Ada has over C/C++). And of course you can just allocate arrays dynamically on the heap using allocators.
如果您希望能够创建判别类型的对象并在运行时更改(或弄清楚)该类型是什么,您必须在声明中为判别式提供默认值。
原因是 Ada 不想担心处理未初始化的可区分对象,因为它甚至无法计算出其大小和有效记录字段。
出于这个原因,以及我在评论中详细讨论的一些原因,Ada 区分记录实际上在混合语言编程中并不是很有用(例如:完全复制 C 联合)。不过,它们可以按照自己的方式方便使用。
对于您给出的示例,您将执行以下操作(警告:未编译):
然后您可以在运行时设置数组值之一:
至于这部分:
myArray :myStruct 的数组(正范围 <>);
您不能像这样声明具有不确定范围的实际数组对象。您可以通过这种方式声明一个类型,但对象必须具有实际大小。如果您想要一个不同长度的数组,您可以再次使用变体记录。 (再次,未编译)
哦,还有一件事。您在示例中没有这样做,但如果您想使用判别式来调整上面的数组大小,请小心。当您声明该类型的对象时(再次假设您使用判别式的默认值),编译器将尝试为您可以为其提供值的最大可能大小保留足够的空间。这使得创建一个由诸如
Integer
或Positive
之类的大范围索引的可区分数组成为一个非常糟糕的想法。我知道现在的计算机越来越大,但大多数人仍然没有 4GB 空间来容纳一个愚蠢的小阵列。因此,如果您使用判别式作为数组索引,那么创建一个较小的 Integer 子类型以用于判别式的类型将是一个好主意。If you want to be able to create objects of a discriminated type and change (or figure out) what the type is at runtime, you have to give the discriminant a default value in the declaration.
The reason for this is that Ada doesn't want to have to worry about dealing with uninitialized discriminated objects that it can't even figure out the size and valid record fields of.
For this reason, and some reasons I go into a bit in the comments, Ada discriminated records aren't actually very useful in mixed language programming (eg: exactly duplicating a C union). They can be handy on their own terms though.
For the example you give, you'd do the following (warning: Not compiled):
Then you could set one of the array values at runtime thusly:
As for this part:
myArray : array (Positive range <>) of myStruct;
You cannot declare actual array objects with an indeterminate range like this. You could declare a type that way, but an object has to have an actual size. If you want an array of varying length, you can once again use a variant record. (Again, not compiled)
Oh, and one more thing. You aren't doing this in your example, but if you ever want to use your discriminant to size an array like above, beware. When you declare objects of that type (again, assuming you used a default for the discriminant), the compiler will try to reserve enough space for the largest possible size you could ever feed it a value for. That makes it a Very Bad Idea to make a discriminated array indexed by something with a huge range like
Integer
orPositive
. I know computers are bigger these days, but still most folks don't have 4 gig to spare for one silly little array. So if you are using your discriminant as an array index, it would be a good idea to create a smaller subtype of Integer to use for the type of the discriminant.