Array of variant records in Ada
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?
The example above will not compile. Here is a correct version (I changed mystruct to Integer for simplicity):
procedure test_array is
subtype Vehicle_Array_Index is Integer range 1..100; --// Maximum size is 100
type Arr_T is array (Vehicle_Array_Index range <>) of Integer;
type Vehicle_Array (Size: Vehicle_Array_Index := 1) is record
Vehicles : Arr_T(1..Size);
end record;
begin
null;
end;
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.
declare
a: array(1..n) of integer; -- n can be a variable here
begin
--some code using a
end;
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.
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):
type myStruct (theType : vehicleType := car) is
record
...
when car => numOfWheels : Positive;
when others => null;
end record;
Then you could set one of the array values at runtime thusly:
myArray(20) := (theType => car,
field1 => myArray(20).field1,
... , --// Fill in the rest of the fields by name
numberOfWheels => 4);
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)
subtype Vehicle_Array_Index is Integer range 1..100; --// Maximum size is 100
type Vehicle_Array (Vehicle_Array_Index : Size := 1) is record
Vehicles : array (Vehicle_Array_Index range <>) of myStruct;
end record;
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
or Positive
. 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.
精彩评论