首页 文章

来自Ada的“操作符号不允许通用子程序”

提问于
浏览
0

我想制作用Ada添加数组元素的子程序 . 子程序“Add_Data”有3个参数 - 第一个参数=泛型类型数组(INTEGER数组或REAL数组)第二个参数= INTEGER(数组大小)第三个参数=泛型类型sum(INTEGER数组 - > sum将是INTEGER,数组真实 - >总和将是真实的)

我是从ideone.com编程的 . (我想通过INTEGER数组看到结果 . 之后,我将通过REAL数组进行测试)

With Ada.Text_IO; Use Ada.Text_IO;  
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure test is
   generic 
      type T is private;
      type Tarr is array (INTEGER range <>) of T;
      --function "+" (A,B : T) return T;
      --function "+" (A, B : T) return T is
      --begin
      --   return (A+B);
      --end "+";
   procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T);

   procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T) is
      temp : T;
      count : INTEGER;
   begin
      count := 1;
      loop
         temp :=temp+  X(count);    //<-This is problem.
         count := count + 1;
         if count > Y then
            exit;
         end if;
      end loop;
      Z:=temp;
   end Add_Data;

   type intArray is array (INTEGER range <>) of INTEGER;
   intArr : intArray := (1=>2, 2=>10, 3=>20, 4=>30, 5=>8);
   sum : INTEGER;
   procedure intAdd is new Add_Data(Tarr=>intArray, T=>INTEGER);

begin
   sum := 0;
   intAdd(intArr, 5, sum);
   put (sum);
end test;

当我不重载运算符“”时,它会产生错误 . “对于私人类型”T“,没有适用的运营商”“ . ”我能为此做些什么?

2 回答

  • 7

    如果泛型的形式类型是 private ,那么泛型中的任何内容都不能假定该类型的任何内容,除了它可以被赋值( := )并且可以比较它的相等性( = )和不等式( /= ) . 特别是,除非您提供,否则通用中不提供其他运算符(例如 + ) .

    这样做的方法是

    generic 
       type T is private;
       with function "+" (L, R : T) return T is <>;
    

    这告诉编译器(a)有一个函数 "+" ,它接受两个 T 并返回一个 T ; (b)如果实际 T 有一个与该配置文件匹配的运算符 "+" ,则允许它作为默认值 .

    所以,你可以说

    procedure intAdd is new Add_Data (T => Integer, ...
    

    或者,如果您不想使用默认值,

    procedure intAdd is new Add_Data (T => Integer, "+" => "+", ...
    
  • 2

    除了不知道如何声明一个通用的正式子程序(Wright已经展示了如何为函数执行此操作)之外,您的代码还有许多其他问题,如果解决这些问题,可能会帮助您从使用其他语言进行思考并转换为其他人它进入Ada成为真正使用Ada的人 . 假设你想成为这样一个人,我会指出其中一些 .

    使用 Integer range <> 声明数组类型 . 在Ada中使用 Positive range <> 比较常见,因为人们通常会提到从1开始的位置:第1,第2,第3 ......

    泛型用于代码重用,在现实生活中,这些代码通常由原作者以外的人使用 . 优良做法是不对客户将传递给您的运营的 Value 做出未说明的假设 . 您假设,对于Y> 0, for all I in 1 .. Y => I in X'range 和Y <1, 1 in X'range . 虽然这对于您使用的值是正确的,但是将数据聚合写为 (2, 10, 20, 30, 8) 会更自然 . 如果我这样做,Intarr 'First = Integer' First和Intarr 'Last = Integer' First 4,两者都是否定的 . 尝试将此索引为1将引发Constraint_Error .

    Y被声明为整数,这意味着零和负值是可接受的 . 将-12传递给Y是什么意思? Ada的亚型有助于此;如果您将Y声明为正数,则尝试将非正值传递给它将失败 .

    Z被声明为模式 in out ,但未引用输入值 . 这将更好,因为模式 out .

    不需要Y.阿达有真正的阵列;他们带着他们的边界作为X'First,X'Last和X'Length . 尝试将数组索引到其边界之外是一个错误(没有缓冲区溢出漏洞可能) . 迭代数组的常用方法是使用'range属性:

    for I in X'range loop
    

    这确保了我始终是X的有效索引 .

    Temp未初始化,因此通常会初始化为“stack junk” . 对于具有相同输入的不同调用,您应该会得到不同的结果 .

    代替

    if count > Y then
            exit;
         end if;
    

    更常见的是写 exit when Count > Y;

    由于您的过程产生单个标量输出,因此它更自然地成为函数:

    generic -- Sum
       type T is private;
       Zero : T;
       type T_List is array (Positive range <>) of T;
       with function "+" (Left : T; Right : T) return T is <>;
    function Sum (X : T_List) return T;
    
    function Sum (X : T_List) return T is
       Result : T := Zero;
    begin -- Sum
       Add_All : for I in X'range loop
          Result := Result + X (I);
       end loop Add_All;
    
       return Result;
    end Sum;
    

    HTH

相关问题