如何声明对泛型中任何子程序形式类型的访问?

时间:2021-05-19 15:26:05

标签: generics ada

我需要制作一个泛型包,它的形参应该是访问子程序的类型。这种类型的对象被传递给这个包的子例程,我必须检查它是否为空相等。

generic
   type Func_Type is private; 
package Gen_Package is
   function Check(Func : Func_Type) return Boolean is
     (Func = null);
end;

但这不能编译,因为比较的左操作数没有访问类型。

3 个答案:

答案 0 :(得分:5)

您可以利用访问类型对象的初始值为 [] 的事实:

null

答案 1 :(得分:3)

您应该指定您需要的访问子程序类型作为形式参数。 Ada 语言参考手册第 12.5.4 节规定:“对于正式访问子程序子类型,指定的正式和实际配置文件应符合子类型。

这导致声明如下:

generic
   type func_type is access function(S : String) return string;
   gen_func : not null func_type;
   type proc_type is access procedure (Msg : in String);
   gen_proc : not null proc_type;
package test_subprog is
   procedure Print;
end test_subprog;

您必须声明对子程序类型的访问权限和对子程序实例的相应访问权限的形式参数。如果您指定形参必须为“非空”,那么您无需在代码中测试空参数。

with Ada.Text_IO; use Ada.Text_IO;

package body test_subprog is

   -----------
   -- Print --
   -----------

   procedure Print is
      Msg : string := "This is a test";
   begin
      Put_Line(Item => gen_func(Msg));
      gen_proc(gen_func(Msg));
   end Print;

end test_subprog;

调用对作为泛型参数传递的子程序的正式访问不需要特殊的语法。制作一个使用泛型包的实际参数的实例可以这样做:

with Ada.text_io; use Ada.Text_IO;
with test_subprog;

procedure Main is
   function format(S : String) return String is
   begin
      return "Called through function access " & S;
   end format;
   
   type format_access is access function(S : string) return String;
   
   procedure reformat(S : String) is
   begin
      Put_Line("Called through procedure access " & S);
   end reformat;
   
   type proc_access is access procedure (S : String);
   
   package sub_test is new test_subprog(func_type => format_access,
                                        gen_func  => format'access,
                                        proc_type => proc_access,
                                        gen_proc  => reformat'access);
begin
   sub_test.print;
end Main;

这种复杂的方法允许您使用对子程序类型的访问作为通用参数。除非您确实需要访问子程序类型,否则可以简单地使用子程序形式参数,如 Ada 语言参考手册第 12.6 节中所述:

通用形式子程序示例:

with function "+"(X, Y : Item) return Item is <>;
with function Image(X : Enum) return String is Enum'Image;
with procedure Update is Default_Update;
with procedure Pre_Action(X : in Item) is null;  -- defaults to no action
with procedure Write(S    : not null access Root_Stream_Type'Class;
                     Desc : Descriptor)
                     is abstract Descriptor'Write;  -- see 13.13.2
-- Dispatching operation on Descriptor with default
--  given the generic procedure declaration 
generic
   with procedure Action (X : in Item);
procedure Iterate(Seq : in Item_Sequence);
--  and the procedure 
procedure Put_Item(X : in Item);
--  the following instantiation is possible 
procedure Put_List is new Iterate(Action => Put_Item);

答案 2 :(得分:2)

<块引用>

在通用数据包中也会传递一个接受这种类型的函数。

也许类似

generic -- GP
   type Func_Ptr (<>) is limited private; -- Expected to be an access type

   with function Is_Null (Ptr : in Func_Ptr) return Boolean;

   with procedure Use_It (Ptr : in Func_Ptr);
package GP is
   procedure Checked_Use (Ptr : in Func_Ptr);
end GP;

package body GP is
   procedure Checked_Use (Ptr : in Func_Ptr) is
      -- Nothing here
   begin -- Checked_Use
      if not Is_Null (Ptr) then
         Use_It (Ptr => Ptr);
      else
         -- Handle null ptr
      end if;
   end Checked_Use;
end GP;

如果没有更多关于您的意图的信息,就很难提供帮助。通常,当您发现自己在与类型系统作斗争时,这表明您遇到了设计问题。

相关问题