Невозможно получить доступ к членам общего параметра ADA

StackOverflow https://stackoverflow.com/questions/2338913

  •  22-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь написать общий пакет, и одна из необходимых операций - это проверить записи данных, полученные на автобусе. Тип записи будет варьироваться, и это общий параметр. Однако любые попытки получить доступ к членам общего параметра вызывают ошибку компиляции.

Ошибка ... (ADA 95 GNAT 2009)

file.adb:XX no selector "Data" for private type "The_Transfer_Type" defined at file.ads:YY

Декларация ...

generic
  type The_Transfer_Type is private;
  SIZE : Integer;
package CC_Test_Channel is
  function Checksum(Msg : The_Transfer_Type) return Integer;
end package

И тело ...

function Checksum(Msg : The_Transfer_Type) return Integer is
  Sum : Integer := 0;
begin
  -- calculate the checksum
  for i in 1 .. SIZE loop
    Sum := Sum + Integer(Msg.Data(i));
  end loop;
  return Sum;
end Checksum;
Это было полезно?

Решение

Когда вы указываете, что общий параметр-это личный тип, в общем, ADA предполагает, что вы это имеете в виду :-)

Т.е. у вас нет доступа к его компонентам. Ада не "утка напечатана«Поэтому не имеет значения, знаете ли вы, что экземпляр типа может действительно обладать определенным полем. (Как бы вы ожидали, что ваша функция контрольной суммы будет работать, если параметр_ transfer_type был создан с, скажем, целым числом?)

Одним из способов устранения этого является также предоставление функции доклада в качестве параметра для общего, который будет извлекать данные, необходимые для того, чтобы в данном случае вычислил контрольную сумму. Например:

generic
   type The_Transfer_Type is private;
   with function Get_Checksummable_Data_Item
           (Msg : The_Transfer_Type;
            I   : Integer) return Integer;
   SIZE : Integer;

package CC_Test_Channel is
   function Checksum(Msg : The_Transfer_Type) return Integer;
end CC_Test_Channel;

Тело тогда:

function Checksum(Msg : The_Transfer_Type) return Integer is
   Sum : Integer := 0;
begin
   -- calculate the checksum
   for i in 1 .. SIZE loop
      Sum := Sum + Get_Checksummable_Data(Msg, I);
   end loop;
   return Sum;
end Checksum;

Функция, которую вы предоставляете для GET_CHECKSUMMABLE_DATA, затем характерна для OFERANSFER_TYPE, и просто возвращает выбранное значение с полей компонентов of_transfer_type.

Существует также ряд других способов настроить это, например, предоставление неограниченного типа массива в качестве общего формального параметра и формальной функции для его извлечения-это позволяет также избавиться от формального параметра явного размера. Или вы можете написать функцию Checksum () как одну из операций на типе, который вы создаете CC_TEST_CHANLER, а затем есть:

with function Calculate_Checksum(Msg : The_Transfer_Type) return Integer;

как один из общих формалов.

Отступите и подумайте о возможностях ...

Другие советы

(переехал из комментария, так как это стало долго)

ADA (95 и позже) поддерживает потоки. В отличие от потоков C ++, которые в значительной степени для преобразования строк, Потоки ADA предназначены как общий механизм для выполнения операций по данным (Обычно ввод/вывод).

У каждого объекта ADA есть 'Write а также 'Read атрибуты. Есть некоторые поставляемые языковые потоки (для ввода/вывода файлов, но у вас также есть возможность создавать свои собственные, выходя из Ada.streams.root_stream_type. Анкет Если вы пишете свой собственный поток таким образом, есть несколько низкоуровневых процедур, которые дают вам прямой доступ к данным.

Это позволяет вам писать свои собственные потоки для выполнения операций, таких как ввод/вывод, сжатие данных, Или в вашем случае, возможно, проверка данных с автобуса Перед загрузкой его в переменные (через «чтение»). В прошлом я делал это, чтобы реализовать функциональность записи/воспроизведения для нашего программного обеспечения в реальном времени. Я тоже один раз просмотрел это для сжатия (мы не нуждались в сжатии).

generic 
  type The_Transfer_Type is private; 
  ...

Приведенный выше код означает, что клиент может предоставить любой тип, который они мечтают для_ the_transfer_type (до тех пор, пока он не «ограничен»). Это также означает, что ваш родовой абсолютно ничего не знает о типе, за исключением того, что поджатие доступно.

С ADA Generics существует своего рода обратная связь между тем, сколько различных видов объектов может быть поставлено для общего параметра, и какие операции поддаются общим для этих объектов. Например, наиболее открытым типом будет is limited private. Анкет Вы можете предоставить любой тип для одного из них. Тем не менее, общий не может ничего не делать с ним. Даже задание не будет доступно.

Уберите «Ограниченное», и вы можете поставить с собой подряд, но могут быть присвоены только типы, которые могут быть назначены. С другой стороны, вы можете определить это как:type The_Transfer_Type is (<>) и тогда вы можете предоставить любой целый ряд или перечисленный тип, и получите такие вещи, как 'first. Анкет Идя еще дальше, вы могли бы сделать type The_Transfer_Type is range <>, и вы получите возможность выполнять целочисленные математические операции, но сможете только поставлять целочисленные числовые типы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top