Flatbeat
Flatbeat

Reputation: 53

Use generic package

my question is very simple. I have 2 generic package. I use each package 2 times (once for integers and strings for once). I have a "main" file that use the package selected by the user. - package1 with integer - or package1 with string - or package2 with integer - or package2 with string

procedure main is
     package aB is new package1(integer, false, afficheInteger, true);
    --package aB is new package1(Unbounded_String, true, afficheUnbounded, true);
    --package aB is new package2(1,integer, false, afficheInteger, true);
    --package aB is new package2(1, Unbounded_String, true, afficheUnbounded, true);

begin aB.init(); .....

The goal is to use the same code (main) for the 4 packages.

Unfortunately I can't find how to do this properly. For the moment I put the list of packages and I comment the packages i don't use. Is it possible to make pseudo if in the begin or init the package in the begin ? Maybe with a package parameter in the main function ?

Thanks a lot and sorry for my english !

Update :

Is it possible to pass a package parameter in a function ? Like this :

procedure init_paquetage1_int is
    package aB is new packA(integer, false, afficheInteger, true);
begin
    main(aB);
end init_paquetage1_int; 

procedure main(aB : packA) is
begin
    aB.init();
    ....
end main;

It's not working.

Upvotes: 2

Views: 1884

Answers (2)

T.E.D.
T.E.D.

Reputation: 44804

OK. First off, I don't see any way you could hope for this to work, unless the routines you are calling in the package(s) have the same parameter profile regardless of which type was used. Typically a generic package will have at least one routine that uses one of the types you instantiated it with in the routine's parameters (or as a return type).

If the routines you want to use do in fact have identical profiles, I can think of a couple of things you could do. The first is to use a pointer to the routine you want to call, and pass that in.

   type Init_Routine is access procedure ();
begin
   main (ab.Init'access);

The second would be to make your generic packages all contain tagged types derived from a common parent abstract tagged type that has the routines you want to call defined as abstract routines in the parent. If you do that, you can use dynamic dispatch to select between them at runtime.

package Parent is
   type Instance is abstract tagged null record;
   type Dispatching_Instance_Ptr is access all Instance;
   procedure Init (I : in out Instance) is abstract;
end Parent;

generic 
   --// Whatever your generic parameters are...
Package1 is
    type Instance is new Parent.Instance with null record;
    procedure Init (I : in out Instance);
    ...
end Package1;
--// (Package2 looks similar)

Skipping down to the calling code:

    Choice : Parent.Dispatching_Instance_Ptr;
begin
    --// Let's assume the user "chooses" package aB
    Choice := new'aB.Instance;
    main (Choice);

...and for main:

procedure main(xx : in Parent.Dispatching_Instance_Ptr) is
begin
   Parent.Init(xx.all);  --// This should dynamic dispatch to the proper init routine
   ....
end main;

Note: I haven't run this through a compiler, so there are probably minor issues. I've found and fixed a couple already.

Upvotes: 6

dalenkruse
dalenkruse

Reputation: 240

Each time you instantiate a generic package, it is treated as a separate package. Therefore, you need to use a different package name for each instantiation.

procedure main is
     package aA is new package1(integer, false, afficheInteger, true);
     package aB is new package1(Unbounded_String, true, afficheUnbounded, true);
     package aC is new package2(1,integer, false, afficheInteger, true);
     package aD is new package2(1, Unbounded_String, true, afficheUnbounded, true);
...

You can now use each of these as a separate package.

aA.init();
aB.init();
...

You can pass in procedures as parameters, but not packages.

If you're still confused on generics, I suggest you read http://en.wikibooks.org/wiki/Ada_Programming/Generics

Upvotes: 2

Related Questions