«Символ оператора не разрешен для общей подпрограммы» от Ады - PullRequest
0 голосов
/ 02 июня 2018

Я хочу сделать подпрограмму для добавления элементов массива с помощью Ada.подпрограмма «Add_Data» имеет 3 параметра - первый параметр = массив универсального типа (массив INTEGER или массив REAL) второй параметр = INTEGER (размер массива) третий параметр = сумма универсального типа (массив INTEGER -> сумма будет INTEGER, массивREAL -> сумма будет 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;

, когда я не перегружаю оператор "+", он делает ошибку.Msgstr "Не существует применимого оператора" + "для частного типа" T "."Что я могу сделать для этого?

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Помимо того, что вы не знаете, как объявлять общую формальную подпрограмму (Райт показал, как это сделать для функций), в вашем коде есть ряд других проблем, которые, если их устранить, могут помочь вам отойти от того, кто думает о другомязык и переводит его на Ада в тот, кто на самом деле использует Ада.Предполагая, что вы хотите стать таким человеком, я укажу некоторые из них.

Вы объявляете свои типы массивов, используя Integer range <>.В Аде более распространено использование Positive range <>, потому что люди обычно ссылаются на позиции, начинающиеся с 1: 1, 2, 3, ...

Обобщения используются для повторного использования кода, а в реальной жизни такой кодчасто используется людьми, отличными от первоначального автора.Рекомендуется не делать необоснованных предположений о значениях, которые клиенты передадут вашим операциям.Вы предполагаете, что для Y> 0 for all I in 1 .. Y => I in X'range и для Y <1 <code>1 in X'range.Хотя это верно для значений, которые вы используете, это вряд ли будет верно для всех применений процедуры.Например, когда массив используется как последовательность, как и здесь, индексы не имеют значения, поэтому более естественно записать ваш массив в виде (2, 10, 20, 30, 8).Если я это сделаю, Intarr'First = Integer'First и Intarr'Last = Integer'First + 4, оба из которых являются отрицательными.Попытка индексировать это с 1 вызовет Constraint_Error.

Y объявлен как Integer, что означает, что нулевые и отрицательные значения являются приемлемыми.Что значит передать -12 в Y?Здесь помогают подтипы Ады;если вы объявите Y как положительное, попытка передать ему не положительные значения завершится неудачей.

Z объявлен в режиме in out, но на входное значение не ссылаются.Это было бы лучше, так как режим out.

Y не нужен.Ада имеет реальные массивы;они носят свои границы с собой как X'First, X'Last и X'Length.Попытка индексировать массив за его пределами является ошибкой (уязвимости переполнения буфера невозможны).Обычный способ итерации по массиву - с помощью атрибута range:

for I in X'range loop

Это гарантирует, что I всегда является допустимым индексом для X.

Temp не инициализируется, поэтому он будетобычно инициализируется как "стек мусора".Вы должны ожидать получения разных результатов для разных вызовов с одними и теми же входами.

Вместо

     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

0 голосов
/ 02 июня 2018

Если формальный тип универсального объекта равен 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, "+" => "+", ...
...