Why is implicit conversion between anonymous access objects disallowed in Ada?

怎甘沉沦 提交于 2020-01-04 05:15:12

问题


I am working my way through Barnes' book 'Programming in Ada 2012'. This is a code sample implementing a stack from section 12.5.

src/stacks.adb: (the main relevant file)


package body Stacks is

   procedure Push(S: in out Stack; X: in Integer) is
   begin
      S := new Cell'(S,X);
   end Push;

   procedure Pop(S: in out Stack; X: in out Integer) is
   begin
      X := S.Value;
      S := Stack(S.Next);
   end Pop;

   function "="(S, T: Stack) return Boolean is
      SS: access Cell := S;
      TT: access Cell := T;
   begin
      while SS /= null and TT /= null loop
         if SS.Value /= TT.Value then
            return false;
         end if;
         SS := SS.Next;
         TT := TT.Next;
      end loop;
      return SS = TT; -- error: implicit conversion of stand-alone anonymous access object not allowed
   end "=";

end Stacks;

I have added a comment containing the error that gnat gives me. Why am I not allowed to convert from one anonymous access Cell to another?

I can solve the problem by inverting the condition:

return not (SS /= TT);

It mystifies me as John Barnes states earlier that if you define a "=" operator returning a boolean, then the inverse "/=" is generated automatically for you, meaning the opposite.

Similarly, the loop condition can be inverted, in which case it fails to compile with the same message.

Finally, a side-note: the expected behaviour of the program, which it gives after changing to return not (SS /= TT) is to recurse infinitely and raise a storage_error due to stack overflow. The reason for that is better seen in this other SO question, and is not the subject of this question.

Why is the conversion disallowed by the compiler when I write "="? Why is it different when I write "/=", which I thought would always be the inverse?

The other files needed in order to compile the example for yourself:

src/stacks.ads:

package Stacks is

   type Stack is limited private;

   procedure Push(S: in out Stack; X: in Integer);
   procedure Pop(S: in out Stack; X: in out Integer);
   function "="(S, T: Stack) return Boolean;

private

   type Cell is
      record
         Next: access Cell;
         Value: Integer;
      end record;
   type Stack is access all Cell;

end;

src/main.adb:

with Ada.Text_IO; use Ada.Text_IO;
with Stacks; use Stacks;

procedure Main is
   A : Stack;
   B : Stack;
begin
   Push(A, 1);
   Push(B, 1);
   Push(A, 2);
   Push(B, 2);
   Push(A, 1);
   Push(B, 1);
   Push(A, 8);
   Push(B, 8);

   declare
      Same : Boolean := A = B;
      Text : String := (if Same then "They are the same" else "They are not the same");
   begin
      Put_Line(Text);
   end;
end Main;

stacks.gpr:

project stacks is
   for Source_Dirs use ("src");
   for Object_Dir use "obj";
   for Main use ("main.adb");
end stacks;

Makefile:

all:
    gprbuild -d -p -g

clean:
    rm -rf obj *.o *.ali

Or compile with gcc:

gcc -c src/*.adb
gnatbind main
gnatlink main

It gives the same results.

来源:https://stackoverflow.com/questions/59410704/why-is-implicit-conversion-between-anonymous-access-objects-disallowed-in-ada

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!