Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top