【问题标题】:"operator symbol not allowed for generic subprogram" from Ada来自 Ada 的“通用子程序不允许使用运算符符号”
【发布时间】:2018-06-02 15:34:12
【问题描述】:

我想用 Ada 制作添加数组元素的子程序。 子程序“Add_Data”有 3 个参数—— 第一个参数 = 泛型数组(INTEGER 数组或 REAL 数组) 第二个参数 = INTEGER(数组大小) 第三个参数 = 泛型 sum(INTEGER 数组 -> sum 为 INTEGER,REAL 数组 -> sum 为 REAL)

我从 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”定义的适用运算符“+”。 我可以为此做些什么?

【问题讨论】:

    标签: operator-overloading ada


    【解决方案1】:

    如果泛型的正式类型是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 &lt;&gt; 声明您的数组类型。在 Ada 中使用Positive range &lt;&gt; 更为常见,因为人们通常指的是从 1 开始的位置:1st, 2nd, 3rd, ...

      泛型用于代码重用,而在现实生活中,此类代码经常被原作者以外的人使用。最好不要对客户将传递给您的运营的价值做出未说明的假设。您假设,对于 Y > 0,for all I in 1 .. Y =&gt; I in X'range,对于 Y 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 声明为 Positive,则尝试将非正值传递给它将会失败。

      Z 声明为模式in out,但未引用输入值。这会更好作为模式out

      不需要Y。 Ada 有真正的数组;它们以 X'First、X'Last 和 X'Length 的形式随身携带。尝试在其边界之外对数组进行索引是错误的(不可能存在缓冲区溢出漏洞)。遍历数组的常用方法是使用 'range 属性:

      for I in X'range loop
      

      这确保 I 始终是 X 的有效索引。

      Temp 没有被初始化,所以它通常会被初始化为“stack junk”。对于使用相同输入的不同调用,您应该期望得到不同的结果。

      代替

           if count > Y then
              exit;
           end if;
      

      exit when Count &gt; 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

      【讨论】:

        猜你喜欢
        • 2017-02-14
        • 2012-05-19
        • 2012-10-30
        • 1970-01-01
        • 1970-01-01
        • 2015-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多