Может ли дискриминант записи косвенно определять длину массива в Ada? - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь объяснить особый случай, когда несколько длин массива должны быть короче, чем обычно, но где нет прямой связи между дискриминантом и длиной массива. Упрощенная запись может выглядеть так в обычном случае:

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;

Но если какой-то дискриминант равен 320, он должен выглядеть так:

type My_Record is
record
    A : Integer;
    B : Integer;
    C : Int_Array(1..4);
    D : Int_Array(1..2);
end record;

Я вроде как с этим немного поиграл, но ничего не могу скомпилировать. Вот несколько вещей, которые я пробовал:

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;

Но это приводит к ошибке "дискриминант в ограничении должен появляться один".

Если я попытаюсь:

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;

Определения C и D противоречат друг другу. Есть ли какая-то другая техника, которую я могу использовать для этого?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Если вы хотите получить доступ к переменным с помощью .C и .D независимо от варианта, вы можете использовать функции доступа:

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

Используя аксессор с Implicit_Dereference, вы можете присваивать значения, как если бы это было поле записи.

0 голосов
/ 28 августа 2018

В выражении case используйте разные имена переменных в каждом случае. Исходные примеры содержат несколько синтаксических ошибок.

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