En Ada, ¿cómo podría hacer subtipo de registros?
Pregunta
Si tengo un tipo de registro como este:
type ABC is record
A : Integer;
B : Integer;
end record;
¿Cómo podría crear un subtipo de ABC con dos tipos de enteros cuyo rango se especifican?
Solución
Mientras no contesta su pregunta per se (como dice NWS, no puede hacerlo), si en lugar de A y B, que son enteros, deberían ser matrices, puede hacer lo siguiente:
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;
Los campos de registro A y B utilicen el subtipo de índice según lo proporcionado por los discriminantes registrados.
Este es un buen truco que he usado de vez en cuando, útil al leer en cadenas de longitud variable de una interfaz (como un zócalo) donde se suministra el número de bytes a lectura a través del encabezado de tamaño fijo;o en el caso de un registro variante con una enumeración discriminante, puedo subtipo del registro a una variante específica.
Otros consejos
También podría usar un genérico, como este:
generic
type Number is range <>;
package Int_Record is
type ABC is record
A, B : Number;
end record;
end Int_Record;
Si desea diferentes rangos para A y B, tendrías que usar dos parámetros genéricos.
El uso sería así:
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;
En Ada 2012
, ahora tenemos Dynamic_Predicate
con lo que podemos imponer restricciones de subtipos, de la siguiente manera:
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;
DADA:
type ABC is record
A : Integer;
B : Integer;
end record;
Usted podría usar:
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;