首页 文章

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

提问于
浏览
5

我正在尝试编写一个通用包,其中一个操作是校验通过总线接收的数据记录 . 记录类型会有所不同,它是一个通用参数 . 但是,任何访问泛型参数成员的尝试都会导致编译错误 .

错误......(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 回答

  • 3

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

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

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

    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

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

    Ada(95及更高版本)支持流 . 与C流不同,C流几乎用于字符串转换,通常是I / O.

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

    这允许您编写自己的流来执行I / O,数据压缩, or in your case perhaps checksumming data from the bus 之类的操作,然后再将其加载到变量中(通过'Read). I'过去自己完成它来实现我们的实时软件的记录/回放功能 . 我也考虑过压缩一次(我们最终不需要压缩) .

  • 4
    generic 
      type The_Transfer_Type is private; 
      ...
    

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

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

    拿走"limited"并且你可以对它进行取消,但是只能提供可以分配的类型 . 在另一个极端,您可以将其定义为: type The_Transfer_Type is (<>) 然后您可以提供任何整数或枚举类型,并获得像 'first 之类的东西 . 更进一步,你可以做 type The_Transfer_Type is range <> ,你可以进行整数数学运算,但只能提供整数数字类型 .

相关问题