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.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII X-Google-Thread: 103376,3b7d2943d4e48cd3 X-Google-Attributes: gid103376,public From: Damien Carbonne Subject: Re: generic formal primitive [dispatching] operation Date: 2000/09/19 Message-ID: <39C9282A.3865AC9C@free.fr> X-Deja-AN: 671775473 Content-Transfer-Encoding: 8bit References: <39C5321E.805A73D1@free.fr> <8q5c2e$gkt$1@melusine.cuivre.fr.eu.org> X-Accept-Language: en Content-Type: text/plain; charset=iso-8859-1 X-Complaints-To: abuse@proxad.net X-Trace: nnrp3.proxad.net 969397617 212.27.44.165 (Tue, 19 Sep 2000 23:06:57 CEST) Organization: Guest of ProXad - France MIME-Version: 1.0 NNTP-Posting-Date: Tue, 19 Sep 2000 23:06:57 CEST Newsgroups: comp.lang.ada Date: 2000-09-19T00:00:00+00:00 List-Id: Thomas Quinot a �crit : > Dans comp.lang.ada, Damien Carbonne �crit : > > >I would like to create a generic package that has, as formal parameters, > >a tagged type and some primitive dispatching operations on that type. > > > >I have tried this: > > > >generic > > type Root is abstract tagged private; > > with procedure P1 (This : access Root); > > P1 is not a primitive operation of Root, because in instances of your > package, P1 denotes a view of the actual parameter, and does not > declare a subprogram. The subprogram denoted by P1 is thus not > declared in the same declarative_region as type Root, and therefore > does not qualify to be a primitive operation of Root. > > It is unclear to me what you are trying to achieve. Could you be more > specific about what you actually want to do? Right, I will try to give a better description of the problem I have, and why I created the example I gave previously. I would like to create a package that looks like that: -- generic_reference.ads ------------------------------------------------------------------------------------------- with Ada.Finalization; use Ada.Finalization; generic type Transformation is private; with function Identity return Transformation is <>; with function "*" (Left, Rigth : Transformation) return Transformation is <>; type Transformer is abstract tagged limited private; -- Here I believe that these decalaration can match primitive operations of Transformer with function Parent_To_Self (This : access Transformer) return Transformation is <>; with function Self_To_Parent (This : access Transformer) return Transformation is <>; package Generic_References is pragma Elaborate_Body; type Transformer_Ref is access all Transformer'Class; type Reference is limited private; type Reference_Ptr is access all Reference; procedure Set_Parent (This : access Reference; Parent : in Reference_Ptr); procedure Set_Transformer (This : access Reference; Transformer : in Transformer_Ref); function Transformation_Betweeen (Ref_1 : access Reference; Ref_2 : access Reference) return Transformation; private -- Here I want to derive Root and redefine dispatching operations. type Identity_Transformer is new Transformer with null record; function Parent_To_Self (This : access Identity_Transformer) return Transformation; function Self_To_Parent (This : access Identity_Transformer) return Transformation; G_Identity_Transformer : Transformer_Ref := new Identity_Transformer; type Reference is new Limited_Controlled with record null; end record; procedure Initialize (Obj : in out Reference); procedure Finalize (Obj : in out Reference); end Generic_References; ------------------------------------------------------------------------------------------- The objective is to handle the notion of Reference attached to a body, and to provide a simple way to make any location or velocity or acceleration etc ...changes between two any references. >From this package point of view, a Transformation must only have two operations: 1) composition 2) Identity Such a Transformation can be imagined in any Space (2D, 3D, etc) or anything else that has no direct geometric interpretation. The Transformer type must be viewed as a java-like interface. Its role is to provide the transformations between two References (via Parent_To_Self and Self_To_Parent). Initially I had not declared Identity_Transformer in the spec. As I had the error I mentioned previously in the body, I changed the formal part with: type Transformer is abstract tagged limited private; with function Parent_To_Self (This : access Transformer'Class) return Transformation is <>; with function Self_To_Parent (This : access Transformer'Class) return Transformation is <>; But then , when I declared the derived type Identity_Transformer I had other errors with overriding of operations of Transformer. So, in fact I happen to ask myself what was the difference between: type Root is abstract tagged private; with procedure P1 (This : access Root); and: type Root is abstract tagged private; with procedure P1 (This : access Root'Class); The first solution seems to allow derivation (Identity_Transformer) and to handle dispatching, but I don't know how to use the operations in the body, whilst the second solution reverses the problem. I know that if the Transformer type was defined in the spec of the generic there would not be any problem. But I don't want to do it for the following reason: The actual Transformer type may derive or not from a base type. And I don't want to write two versions of the package, one with a base type, and the other without any base type. This is why I would like to define a formal generic "interface" (abstract class + operations) that can be "implemented" or derived in the generic (e.g., Identity_Transformer) and that can be used in the body! As I have not found any clear (for me) explanation in the RM about formal primitive operations, I tried simple examples (I know, examples are not proof!) like: ------------------------------------------------------ generic type Root is abstract tagged private; with procedure P1 (This : access Root); package Generic_Deriveds is type Derived is new Root with null record; procedure P1 (This : access Derived); end Generic_Deriveds; with Ada.Text_IO; package body Generic_Deriveds is procedure P1 (This : access Derived) is begin Ada.Text_IO.Put_Line("Generic_Deriveds.Derived.P1"); end P1; end Generic_Deriveds; package Roots is type Root is tagged null record; procedure P1 (This: access Root); end Roots; with Ada.Text_IO; package body Roots is procedure P1 (This: access Root) is begin Ada.Text_IO.Put_Line("Roots.Root.P1"); end P1; end Roots; with Roots; with Generic_Deriveds; package Deriveds is new Generic_Deriveds(Roots.Root, Roots.P1); with Roots; use Roots; with Deriveds; use Deriveds; procedure Main is R : aliased Root; D : aliased Derived; procedure Check (This : access Root'Class) is begin P1(This); end Check; begin Check(R'Access); Check(D'Access); end Main; ------------------------------------------------------- Using gnat 3.13a, this compiles and works as I expect (at least I believe it !), it prints: Roots.Root.P1 Generic_Deriveds.Derived.P1 And, if I suppress the definition of P1 in Generic_Deriveds, the output is: Roots.Root.P1 Roots.Root.P1 So this example makes me think that in the declaration: generic type Root is abstract tagged private; with procedure P1 (This : access Root); P1 is a (or may be) interpreted by the compiler as a primitive operation. The only problem I have is the one illustrated in the first post: I can not use dispatching in the body (or I don't know how to do it) I am afraid to be bit confusing, but I would really like to understand this issue. I whish someone could clarify all this for me! Thanks ! Damien.