无法访问Ada泛型参数的成员

时间:2010-02-26 01:21:07

标签: 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;

3 个答案:

答案 0 :(得分:5)

当您指定泛型参数是私有类型时,Ada假设您的意思是: - )

即。您无法访问其组件。 Ada不是“duck typed”,因此,无论您是否知道实例化类型实际上可能拥有特定字段,都无关紧要。 (如果使用Integer实例化The_Transfer_Type参数,您期望Checksum函数如何工作?)

解决此问题的一种方法是还提供访问器函数作为通用的参数,该参数将检索在这种情况下计算校验和所需的数据。 E.g:

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;

作为通用形式之一。

退一步,考虑可能性......

答案 1 :(得分:4)

(从评论中移除,因为这很长)

Ada(95及更高版本)支持流。与C ++流不同,C ++流几乎用于字符串转换, Ada流意味着作为执行数据操作的通用机制(通常是I / O)。

每个Ada对象都有'Write'Read个属性。有一些语言提供的流(用于文件I / O),但您也可以通过派生Ada.Streams.Root_Stream_Type来创建自己的流。如果以这种方式编写自己的流,则可以使用一些低级例程来直接访问数据。

这允许您编写自己的流来执行诸如I / O,数据压缩,之类的操作,或者在您的情况下执行校验和来自总线的数据,然后再将其加载到变量中(通过“读取”)。我过去自己做过,为我们的实时软件实现记录/回放功能。我也一次调查压缩(我们最终不需要压缩)。

答案 2 :(得分:3)

generic 
  type The_Transfer_Type is private; 
  ...

上述代码意味着客户可以提供他们为The_Transfer_Type预设的任何类型(只要它不是“有限的”)。这也意味着你的泛型对该类型一无所知,除了可以使用asignment。

使用Ada泛型,可以为通用参数提供多少种不同类型的对象,以及哪些操作可用于这些对象上的泛型。例如,最开放的类型是is limited private。您可以为其中一种提供任何类型的任何类型。但是,泛型几乎不能用它做任何事情。甚至分配都不可用。

取走“限制”并可以对其进行取消,但只能提供可分配的类型。另一方面,您可以将其定义为: type The_Transfer_Type is (<>)然后您可以提供任何整数或枚举类型,并获得'first之类的内容。更进一步,你可以做type The_Transfer_Type is range <>,你可以进行整数数学运算,但只能提供整数数字类型。

相关问题