1

I'm having some issues with generics in Ada. Given the below example, gnatmake results in:

g_package.adb:13:33: 'Access attribute not allowed in generic body
g_package.adb:13:33: because access type "t_callback_p" is declared outside generic unit (RM 3.10.2(32))
g_package.adb:13:33: move 'Access to private part, or (Ada 2005) use anonymous access type instead of "t_callback_p"
gnatmake: "g_package.adb" compilation error

With the assumption that the external package cannot be changed, is there a way to solve this? I get the reason for the error message in the first place (compiler doesn't know the proper type of the generic package, but it's a bit annoying when the passed function in question doesn't touch any part of the generic..)

g_package.adb

with Ada.Text_IO; use Ada.Text_IO;
with external;

package body g_package is
   procedure quix (f : String) is
   begin
      Put_Line ("Does a thing");
   end quix;

   procedure foo (bar : String) is
   begin
      Put_Line ("baz" & bar & Boolean'Image(flag));
      external.procedure_f (quix'Access);
   end foo;
end g_package;

g_package.ads

generic
   flag : Boolean;
package g_package is
   procedure foo (bar : String);
end g_package;

external.ads

package external is
   type t_callback_p is access procedure (s : String);
   procedure procedure_f (proc : t_callback_p);
end external;
LordAro
  • 1,269
  • 3
  • 18
  • 35

2 Answers2

5

You can (as mentioned in the error message) move the 'Access to the private part of the package spec:

private with external;

generic
   flag : Boolean;
package g_package is
   procedure foo (bar : String);

private
   procedure quix (f : String);
   quix_access : constant external.t_callback_p := quix'Access;

end g_package;

and the use the constant in the body:

external.procedure_f (quix_access);
egilhh
  • 6,464
  • 1
  • 18
  • 19
  • Perfect, thanks very much. I couldn't quite work out what the error message was talking about, so thanks for explaining it – LordAro Jan 10 '18 at 11:12
  • Spoke too soon - `instantiation.adb:4:01: instantiation error at g_package.ads:9` `instantiation.adb:4:01: subprogram must not be deeper than access type` any ideas? – LordAro Jan 10 '18 at 11:42
  • 1
    You can't instantiate the generic in the main subprogram, it has to be at the same level as the access type, ie. the library level in this case – egilhh Jan 10 '18 at 11:49
0

There's no way to do this in Ada. If you wish to be non-portable and are using (as it appears) GNAT, you can use the GNAT-specific attribute 'Unrestricted_Access.

Jeffrey R. Carter
  • 3,033
  • 9
  • 10