2012-03-10 5 views
0

, если у меня есть тип записи, как это:В Аде, как я могу сделать подтип записей?

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

Как я могу создать подтип ABC с двумя типами Integer, чей диапазон указаны?

+1

Вы не делаете. Подтипирование применимо к перечислениям, поплавкам, целым числам и т. Д., Но не к записям. Если вы предоставите больше информации о своей проблеме, мы сможем помочь вам ... – NWS

+0

'подтип XYZ является ABC;' является законным, но не то, о чем просит OP. –

ответ

3

Пока не отвечая на ваш вопрос по себе (как говорит NWS, вы не можете сделать это), если вместо А и Б целых чисел, они должны были быть массивами, вы можете сделать следующее:

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 используют индексный подтип, как это предусмотрено дискриминаторами записи.

Это хороший трюк, который я использовал время от времени, полезен при чтении строк переменной длины из интерфейса (например, сокета), где количество прочитанных байтов подается через заголовок фиксированного размера; или в случае варианта записи с дискриминантом перечисления я могу подтип записи к конкретному варианту.

2

Вы можете использовать общий тоже, как это:

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

Если вы хотите, чтобы разные диапазоны для А и В, вы должны использовать две общие параметры.

Usage будет выглядеть так:

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; 
0

Дано:

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; 
1

В 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; 
+0

(а) Я думаю, вы имеете в виду 'или еще рейз Constraint_Error'! (b) где в RM это разрешено как определение аспекта? Я вижу, что GNAT GPL 2013 позволяет это (но не FSF GCC 4.8.0), и я вижу, что это имеет смысл здесь. –

+0

С GNAT GPL 2013, используя конструкцию 'или raise Constraint_Error', означает, что исключение сообщается в строке объявления, хотя трассировка показывает неудачное использование. Если вы оставите это, «Assert_Error» сообщается при неудачном использовании, что гораздо более полезно. –

+0

Да, вы правы, это должно быть 'или еще рейз'. Я попытался найти конструкцию в LRM, но не нашел ее. (Я * думаю * Я узнал об этом от Рэнди на comp.lang.ada.) – Shark8