Невозможно получить доступ к членам Ada универсальный параметр

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

Ошибка... (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;
5
задан mat_geek 26 February 2010 в 01:21
поделиться

3 ответа

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

Т.е. у вас нет доступа к его компонентам. Ada не является "duck typed", поэтому не имеет значения, знаете ли вы, что инстанцирующий тип может обладать определенным полем. (Как вы ожидаете, что ваша функция Checksum будет работать, если параметр The_Transfer_Type будет инстанцирован, скажем, Integer?)

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

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, специфична для The_Transfer_Type и просто возвращает выбранное значение из полей компонентов The_Transfer_Type.

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

with function Calculate_Checksum(Msg : The_Transfer_Type) return Integer;

как одну из общих формальных функций.

Сделайте шаг назад и подумайте о возможностях...

5
ответ дан 13 December 2019 в 05:34
поделиться
generic 
  type The_Transfer_Type is private; 
  ...

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

В обобщенных шаблонах Ada существует своего рода обратная связь между количеством различных типов объектов, которые могут быть предоставлены для универсального параметра, и тем, какие операции доступны для универсального шаблона для этих объектов. Например, наиболее открытым типом будет ограничено private . Вы можете предоставить любой тип whatsover для одного из них. Однако общий тип почти ничего не может с ним сделать. Даже назначение не будет доступно.

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

3
ответ дан 13 December 2019 в 05:34
поделиться

(перемещено из комментария, так как он стал длинным)

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

Каждый объект Ada имеет атрибуты «Запись и », чтение . Есть потоки, предоставляемые на некоторых языках (для файлового ввода-вывода), но вы также можете создавать свои собственные, производные от Ada.Streams.Root_Stream_Type . Если вы напишете свой собственный поток таким образом, есть несколько подпрограмм низкого уровня, которые предоставят вам прямой доступ к данным.

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

4
ответ дан 13 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: