如何定义通用元素的数组

时间:2014-12-16 17:00:39

标签: arrays generics ada

在许多来源的帮助下,我对环形缓冲区有一个通用的东西,推送和读取单个元素:

q.ads:

generic
    Q_SIZE : POSITIVE;
    type T is private;
package Q is
    subtype SIZE_TYPE is NATURAL range 0 .. Q_SIZE;
    subtype Q_INDEX_TYPE is SIZE_TYPE range 1 .. SIZE_TYPE'last;
    type Q_ARRAY_TYPE is array (Q_INDEX_TYPE) of T;

    procedure INITIALIZE;
    procedure PUSH(element : T);
    function READ return T;
end Q;

q.adb:

package body Q is
    Q_ARRAY : Q_ARRAY_TYPE;
    TAIL : Q_INDEX_TYPE;
    HEAD : Q_INDEX_TYPE;
    ...
end Q;

我的测试程序实例化上面的字节并练习环。基本如下:

package body main is
    package RING is new Q (15, UNSIGNED.BYTE);
    procedure TEST is
        byteval : UNSIGNED.BYTE;
    begin
        byteval := 16;
        RING.PUSH(byteval);
  ...

我现在想要添加传递T数组的功能。我已经将它添加到ADS和ADB文件中:

    procedure PUSH_ARRAY(DATA_ARRAY : Q_ARRAY_TYPE; COUNT : SIZE_TYPE);

我的问题出在测试程序中。我已将其更改为:

    BYTE_ARRAY : array (1 .. 10) of UNSIGNED.BYTE;
    procedure TEST is begin
        -- initialize the first 5 elements of BYTE_ARRAY, then
        RING.PUSH_ARRAY(BYTE_ARRAY, 5);

这最后一行给出了一条错误消息:在Q.ADS:xx定义的预期类型Q_ARRAY_TYPE。如何将BYTE ARRAY传递给需要通用数组实例的方法?

1 个答案:

答案 0 :(得分:0)

问题:SIZE_TYPE的目的是什么? 在Ada中,'Length属性将返回Natural(非负整数子类型)中数组的大小。考虑到这一点,使用索引的额外值声明额外的子类型似乎没有意义。


Ring_Buffer.ads

Generic
   Type T is private;
   Default : T;
   Size    : Positive;
Package Ring_Buffer is

   SubType Index is Positive range 1..Size;

   Type Ring is private;

   Function  Length( Obj : Ring ) return Natural;

   Function  Pop( Obj : in out Ring ) return T
     with Pre  => Length(Obj) in Positive,
          Post => Length(Obj'Old)-1 = Length(Obj); --' --Highlight fix

   Procedure Push( Obj : in out Ring; Item : in T )
     with Pre  => Length(Obj) < Size,
          Post => Length(Obj'Old)+1 = Length(Obj); --'

Private
   Type Internal_Data is Array(Index) of T;
   Type Ring is record
      Start : Positive:= Internal_Data'First; --'
      Size  : Natural:= 0;
      Data  : Internal_Data:= (Others => Default);
   end record
   with Type_Invariant => Ring.Size <= Size;

   Function Length( Obj : Ring ) return Natural is
      ( Obj.Size );

End Ring_Buffer;

Ring_Buffer.adb

Package Body Ring_Buffer is

   Function  Pop( Obj : in out Ring ) return T is
   Begin
      return Result : constant T := Obj.Data(Obj.Start) do
         Obj.Size:= Natural'Pred( Obj.Size ); --'
         Obj.Start:= (if Obj.Start = Size then 1 else Obj.Start + 1);
      end return;
   End Pop;

   Procedure Push( Obj : in out Ring; Item : in T ) is
   Begin
      Obj.Data( Natural'Succ((Obj.Start-1) + Obj.Size mod Size) ):= Item; --'
      Obj.Size:= Obj.Size + 1;
   End Push;

End Ring_Buffer;