From: Damien Carbonne <damien.carbonne@free.fr>
Subject: Re: generic formal primitive [dispatching] operation
Date: 2000/09/19
Date: 2000-09-19T00:00:00+00:00 [thread overview]
Message-ID: <39C9282A.3865AC9C@free.fr> (raw)
In-Reply-To: 8q5c2e$gkt$1@melusine.cuivre.fr.eu.org
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.
next prev parent reply other threads:[~2000-09-19 0:00 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <39C5321E.805A73D1@free.fr>
2000-09-18 0:00 ` generic formal primitive [dispatching] operation Thomas Quinot
2000-09-19 0:00 ` Damien Carbonne [this message]
2000-09-18 0:00 ` Robert A Duff
2000-09-19 0:00 ` Damien Carbonne
2000-09-19 0:00 ` Robert A Duff
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox