comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Generics with concrete and class-wide types
Date: Tue, 1 Apr 2008 12:53:04 +0200
Date: 2008-04-01T12:53:04+02:00	[thread overview]
Message-ID: <79hzafn3nee9$.kwqz0ce89qar.dlg@40tude.net> (raw)
In-Reply-To: 881a8e2c-01b2-462d-907b-f0887943acf4@a70g2000hsh.googlegroups.com

On Tue, 1 Apr 2008 02:51:19 -0700 (PDT), Maciej Sobczak wrote:

> On 1 Kwi, 11:42, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> Just a small side note. If you care about performance you should do exactly
>> the opposite you tried to, i.e. you should instantiate it with a specific
>> type rather than with a class of.
> 
> This is exactly what I want to do.
> If I have the knowledge of the specific iterator type, I want to
> instantiate the subprogram with this specific type to facilitate
> direct dispatch and code inlining.
> When the only this I have is 'Class, then I want to instantiate the
> subprogram with what I have and agree for indirect dispatch to
> iterator operations within the subprogram body.
> 
> The question is whether it is possible in Ada without walking on the
> edge of compiler conformance - and in particular without accidentally
> benefiting from any compiler bug that will bite me later on when it's
> fixed.
> Yes, some bugs can be harmful after they are fixed. :-)
> 
> I will try the scheme proposed by Georg.

You could also do:

generic
   type Element_Type is private; -- element type
package Iterators is
   type Iterator_Type is interface;
   function Get (I : Iterator_Type) return Element_Type is abstract;
   -- and so on for other operations...
end Iterators;

with Iterators;
generic
   with package Root_Iterators is new Iterators (<>);
   type Base_Iterator_Type is
      new Root_Iterators.Iterator_Type with private;
package Some_Procedure is
   type Iterator_Type is new Base_Iterator_Type with null record;
   procedure Foo (I : Iterator_Type); -- Primitive operation when tagged
end Some_Procedure;

You have to derive from Iterator_Type in order to declare another primitive
operation Foo. The element type comes with the instance of Iterators which
is the first formal parameter. The second formal parameter is a
non-abstract iterator type implementing the iterator interface. This schema
allows to cascade packages like Some_Procedure taking
Some_Procedure_1_Instance.Iterator_Type as the parameter for
Some_Procedure_2_Instance. Base_Iterator_Type could also be abstract, but
that would more difficult to trace instantiation problems.

Example:

with Ada.Finalization;
with Iterators, Some_Procedure;

procedure Test_Iterators is

   ------ Iterators to tagged elements -----------
   type My_Element is new Ada.Finalization.Controlled with null record;
   package My_Element_Iterators is new Iterators (My_Element);

   package Firewall_1 is
      type My_Iterator is
         new My_Element_Iterators.Iterator_Type with null record;
      function Get (I : My_Iterator) return My_Element;
   end Firewall_1;

   package My_Element_SP is
      new Some_Procedure (My_Element_Iterators, Firewall_1.My_Iterator);

   ------- Iterators to integer elements -------
   package Integer_Iterators is new Iterators (Integer);
   package Firewall_2 is
      type Integer_Iterator is
         new Integer_Iterators.Iterator_Type with null record;
      function Get (I : Integer_Iterator) return Integer;
   end Firewall_2;

   package Integer_SP is
      new Some_Procedure (Integer_Iterators, Firewall_2.Integer_Iterator);

   ---------------------------------------------------------
   package body Firewall_1 is
      function Get (I : My_Iterator) return My_Element is
      begin
         return (Ada.Finalization.Controlled with null record);
      end Get;
   end Firewall_1;

   package body Firewall_2 is
      function Get (I : Integer_Iterator) return Integer is
      begin
         return 5;
      end Get;
   end Firewall_2;
   
begin
   null;
end Test_Iterators;

The packages like Firewall are needed to freeze the element type.
Otherwise, the compiler would yell that

    function Get (I : My_Iterator) return My_Element;

is doubly dispatching.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



      reply	other threads:[~2008-04-01 10:53 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-31 20:22 Generics with concrete and class-wide types Maciej Sobczak
2008-03-31 23:38 ` Adam Beneschan
2008-04-01 20:10   ` Randy Brukardt
2008-04-01 21:17     ` Adam Beneschan
2008-04-01  0:23 ` Randy Brukardt
2008-04-01  3:57   ` Eric Hughes
2008-04-01  6:58     ` christoph.grein
2008-04-01  7:22 ` Georg Bauhaus
2008-04-01  9:42 ` Dmitry A. Kazakov
2008-04-01  9:51   ` Maciej Sobczak
2008-04-01 10:53     ` Dmitry A. Kazakov [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox