From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,f5b0e4b29b2f0c99 X-Google-Attributes: gid103376,public From: "David C. Hoos, Sr." Subject: Re: Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html? Date: 1999/04/07 Message-ID: <5VxQ6WNg#GA.143@pet.hiwaay.net>#1/1 X-Deja-AN: 463573888 Content-Transfer-Encoding: 7bit References: <01be80c2$114e0890$c24d3a8b@m04w0588> Content-Type: text/plain; charset="iso-8859-1" X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3 MIME-Version: 1.0 Newsgroups: comp.lang.ada Date: 1999-04-07T00:00:00+00:00 List-Id: Daniel Wengelin wrote in message <01be80c2$114e0890$c24d3a8b@m04w0588>... > > >When looking around for some infomration about OOP I came across the >article http://www.adahome.com/articles/1998-02/ar_lessons95.html. > >I gave the code a try with Gnat 3.11 as follows. > >generic > type Item_T is private; >package List is > type Node; > type Object is access Node; > type Node is record > I : Item_T; > Next:Object; > end record; > > type Action_Proc is access procedure > (I : in out Item_T); > procedure Iterate > (The_Action : Action_Proc; > Through_List : Object); >end List; > >--------------------------- >package body List is > procedure Iterate > (The_Action : Action_Proc; > Through_List : Object) > is > Current : Object := Through_List; > begin > while Current /= null loop > The_Action(Current.I); > Current := Current.Next; > end loop; > end Iterate; >end List; > >------------------------ > >procedure List_Test is > > procedure Print (C: in out Character) is > begin > Ada.Text_Io.Put(C); > Ada.Text_Io.New_Line; > end Print; > package C_List is new List(Character); > > The_List : C_List.Object := null; >begin > for I in Character range 'a' .. 'e' loop > The_List := new C_List.Node'(I, The_List); > end loop; > > C_List.Iterate (Print'Access, The_List); >end List_Test; > >The above source compiled and ran without any problems. So, did I >misunderstand or is Gnat wrong or is the article in AdaHome wrong? > Well, you must have an amazing version of gnat-3.11, for your code won't compile either without the required context clauses for Ada.Text_IO, and List in the List_Test source file ;). But, seriously, I am glad to say Jean-Marie Dautelle is incorrect in the article you cited. Indeed I have used access to subprograms many times in multi-tasking programs. The basic rule is that accesses to subprograms must not have a lifetime greater than that of the subprogram. So, in your example, even though the procedure Print only exists during the execution of procedure List_Test, there is no problem because the lifetime of Print cannot be less than that of the access type C_List.Action_Proc; Frequently, all this limitation means is that the subprogram must be declared at library level -- i.e. such that the lifetime of the subprogram is the same as that of the main program. For example, if you make this small change to your code (leaving the generic List package unchanged, the program will not compile: ---- with List; package C_List is new List(Character); ---- with Ada.Text_IO; with C_List; procedure List_Test is procedure Print (C: in out Character) is begin Ada.Text_IO.Put(C); Ada.Text_IO.New_Line; end Print; The_List : C_List.Object := null; begin for I in Character range 'a' .. 'e' loop The_List := new C_List.Node'(I, The_List); end loop; C_List.Iterate (Print'Access, The_List); end List_Test; ---- In this case, the access type C_List.Action_Proc could have a lifetime greater than that of the subprogram Print. When gcc compiles List_Test, it has no way of knowing that List_Test is the main program, so the compilation fails. As the RM puts it, the subprogram access level is deeper than that of the access type, which is not allowed. But what if the generic instantiation C_List is to be used by more than one compilation unit, and therefore must be declared at library level? Again, another small change makes things well again. with List; package C_List is new List(Character); ---- with Ada.Text_IO; procedure Print (C: in out Character) is begin Ada.Text_IO.Put(C); Ada.Text_IO.New_Line; end Print; ---- with C_List; with Print; procedure List_Test is The_List : C_List.Object := null; begin for I in Character range 'a' .. 'e' loop The_List := new C_List.Node'(I, The_List); end loop; C_List.Iterate (Print'Access, The_List); end List_Test; ---- Now, once again, the lifetime of Print is at least as long as that of the access type C_List.Action_Proc.