Reputation: 498
I'm trying to account for a special case in which several array lengths should be shorter than normal, but where there's no direct relationship between the discriminant and the array lengths. A simplified record might look like this in the normal case:
type Int_Array is array(Integer range <>);
type My_Record is
record
A : Integer;
B : Integer;
C : Int_Array(1..10);
D : Int_Array(1..6);
end record;
But if some discriminant is 320, it should look like this:
type My_Record is
record
A : Integer;
B : Integer;
C : Int_Array(1..4);
D : Int_Array(1..2);
end record;
I've kinda been playing around with it some but can't make anything compile. Here are some things I've tried:
type My_Record(Disc : Positive) is
record
A : Integer;
B : Integer;
C : Int_Array(1..(if Disc = 320 then 4 else 10));
D : Int_Array(1..(if Disc = 320 then 2 else 4));
end record;
But this results in the error "discriminant in constraint must appear alone".
If I try:
type My_Record(Disc : Positive) is
record
A : Integer;
B : Integer;
case Disc is
when 320 =>
C : Int_Array(1..4);
D : Int_Array(1..2);
when others =>
C : Int_Array(1..10);
D : Int_Array(1..4);
end case;
end record;
The definitions of C and D conflict with each other. Is there some other technique I can use for this?
Upvotes: 3
Views: 353
Reputation: 39668
If you want to access the variables with .C
and .D
regardless of the variant, you could use accessor functions:
type My_Record (IDisc : Positive) is record
IA, IB : Integer;
case Disc is
when 320 =>
C1 : aliased Int_Array (1 .. 4);
D1 : aliased Int_Array (1 .. 2);
when others =>
C2 : aliased Int_Array (1 .. 10);
D2 : aliased Int_Array (1 .. 4);
end case;
end record;
type Int_Array_Accessor (Data : not null access all Int_Array) is
limited null record with Implicit_Dereference => Data;
function C (Object : in out My_Record) return Int_Array_Accessor is
(Int_Array_Accessor'(if Object.Disc = 320 then
Object.C1'Access else Object.C2'Access));
function D (Object : in out My_Record) return Int_Array_Accessor is
(Int_Array_Accessor'(if Object.Disc = 320 then
Object.D1'Access else Object.D2'Access));
By using an accessor with Implicit_Dereference
, you can assign values as if it was a record field.
Upvotes: 4
Reputation: 5021
In the case statement use different variable names in each case. Your original examples contain a few syntax errors.
package foo is
type Int_Array is array(Integer range <>) of Integer;
type My_Record(Disc : Positive) is
record
A : Integer;
B : Integer;
case Disc is
when 320 =>
C : Int_Array(1..4);
D : Int_Array(1..2);
when others =>
E : Int_Array(1..10);
F : Int_Array(1..4);
end case;
end record;
end foo;
Upvotes: 2