user1065942
user1065942

Reputation:

In Ada, how could I make subtype of records?

if I have a record type like this:

  type ABC is record
       A : Integer;
       B : Integer;
  end record;

How could I create a subtype of ABC with two Integer types whose range are specified?

Upvotes: 0

Views: 1274

Answers (4)

Shark8
Shark8

Reputation: 4198

In Ada 2012 we now have Dynamic_Predicate with which we can impose subtyping restrictions, as follows:

type ABC is record
    A : Integer;
    B : Integer;
  end record;

subtype XYZ is ABC
  with dynamic_predicate => 
  ((XYZ.A in Positive) and
   (XYZ.B not in Positive)) or else raise Constraint_Error;

Upvotes: 3

Shark8
Shark8

Reputation: 4198

Given:

type ABC is record
   A : Integer;
   B : Integer;
end record;

You could use:

type XYZ is record
   A : Positive;  -- A is subtype of ABC.A
   B : Natural;   -- B is subtype of ABC.B
end record;

  function convert(Input: ABC) return XYZ is
  begin
     return Result : XYZ:= ( A => Input.A, B => Input.B );
  -- Put your exception handling here.
  end convert;

Upvotes: 0

Rommudoh
Rommudoh

Reputation: 1804

You could use a generic too, like this:

generic
   type Number is range <>;
package Int_Record is
   type ABC is record
      A, B : Number;
   end record;
end Int_Record;

If you want different ranges for A and B, you'd have to use two generic parameters.

Usage would be like this:

procedure Foo is
   subtype My_Int is Integer range 1 .. 3;
   package My_Int_Record is new Int_Record (Number => My_Int);
   X : My_Int_Record.ABC;
begin
   X.A := 2; -- okay
   X.B := 4; -- error!
end Foo;

Upvotes: 0

Marc C
Marc C

Reputation: 8522

While not answering your question per se (as NWS says, you can't do that), if instead of A and B being integers, they were to be arrays, you can do the following:

package Record_Subtypes is

   type Int_Data is array (Integer range <>) of Integer;

   type ABC (X_Min, X_Max, Y_Min, Y_Max : Integer) is record
      A : Int_Data (X_Min .. X_Max);
      B : Int_Data (Y_Min .. Y_Max);
   end record;

   subtype ABC_4_4 is ABC(X_Min => 1, X_Max => 4,
                          Y_Min => 1, Y_Max => 4);

   subtype ABC_1_7_3_12 is ABC (X_Min => 1, X_Max => 7,
                                Y_Min => 3, Y_Max => 12);
end Record_Subtypes;

The A and B record fields then utilize the index subtype as provided by the record discriminants.

This is a nice trick I've used from time to time, useful when reading in variable length strings from an interface (such as a socket) where the number of bytes to read is supplied via fixed-sized header; or in the case of a variant record with an enumeration discriminant, I can subtype the record to a specific variant.

Upvotes: 3

Related Questions