если у меня есть такой тип записи:
type ABC is record
A : Integer;
B : Integer;
end record;
Как я могу создать подтип ABC с двумя типами Integer, диапазон которых указан?
если у меня есть такой тип записи:
type ABC is record
A : Integer;
B : Integer;
end record;
Как я могу создать подтип ABC с двумя типами Integer, диапазон которых указан?
Не отвечая на ваш вопрос как таковой (как говорит NWS, вы не можете этого сделать), если вместо A и B быть целыми числами, они должны быть массивами, вы можете сделать следующее:
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;
Поля записи A и B затем используют подтип индекса, предоставленный дискриминантами записи.
Это хороший трюк, который я использовал время от времени, полезный при чтении строк переменной длины из интерфейса (например, сокета), где количество байтов для чтения предоставляется через заголовок фиксированного размера; или в случае записи варианта с дискриминантом перечисления я могу подтипировать запись к определенному варианту.
Вы также можете использовать универсальный, например:
generic
type Number is range <>;
package Int_Record is
type ABC is record
A, B : Number;
end record;
end Int_Record;
Если вам нужны разные диапазоны для A и B, вам придется использовать два общих параметра.
Использование будет таким:
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;
В Ada 2012
у нас теперь есть Dynamic_Predicate
, с помощью которого мы можем наложить ограничения на подтипы следующим образом:
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;
or else raise Constraint_Error
! (b) где в РМ это разрешено в качестве определения аспекта? Я вижу, что GNAT GPL 2013 разрешает это (но не FSF GCC 4.8.0), и я вижу, что здесь это имеет смысл.
- person Simon Wright; 31.10.2013
or raise Constraint_Error
означает, что об исключении сообщается в строке объявления, хотя трассировка показывает неудачное использование. Если вы его не укажете, при неудачном использовании будет сообщено Assert_Error
, что гораздо полезнее.
- person Simon Wright; 01.11.2013
or else raise
. Я попытался найти конструкцию в LRM, но не нашел. (Я думаю, я узнал об этом от Рэнди на comp.lang.ada.)
- person Shark8; 02.11.2013
Данный:
type ABC is record
A : Integer;
B : Integer;
end record;
Вы можете использовать:
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;
subtype XYZ is ABC;
является законным, но не тем, о чем просит ОП. - person Keith Thompson   schedule 10.03.2012