如何在泛型中声明对任何子程序形式类型的访问?
How to declare access to any subprogram formal type in generic?
我需要做一个泛型包,其形参应该是子程序的访问类型。这种类型的对象被传递给这个包的子例程,我必须检查它是否相等。
generic
type Func_Type is private;
package Gen_Package is
function Check(Func : Func_Type) return Boolean is
(Func = null);
end;
但这无法编译,因为比较中的左操作数没有访问类型。
您可以利用访问类型对象的初始值为null
:
这一事实
generic
type Func_Type is private;
-- make comparison operator available. `is <>` means it does not
-- need to be given explicitly if it is visible at the site of instantiation.
with function "=" (Left, Right : Func_Type) return Boolean is <>;
package Gen_Package is
function Check (Func : Func_Type) return Boolean;
end Gen_Package;
package body Gen_Package is
function Check (Func : Func_Type) return Boolean is
-- not constant because we cannot give an initialization expression.
-- if Func_Type is an access type, Null_Value will be initialized with null.
Null_Value : Func_Type;
begin
return Func = Null_Value;
end Check;
end Gen_Package;
您应该指定您需要的子程序访问类型作为您的形式参数。
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);
In generic packet will also be passed a function that accepts this type.
也许像
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;
?
如果没有关于您的意图的更多信息,很难提供帮助。通常,当您发现自己与类型系统作对时,这表明您存在设计问题。
我需要做一个泛型包,其形参应该是子程序的访问类型。这种类型的对象被传递给这个包的子例程,我必须检查它是否相等。
generic
type Func_Type is private;
package Gen_Package is
function Check(Func : Func_Type) return Boolean is
(Func = null);
end;
但这无法编译,因为比较中的左操作数没有访问类型。
您可以利用访问类型对象的初始值为null
:
generic
type Func_Type is private;
-- make comparison operator available. `is <>` means it does not
-- need to be given explicitly if it is visible at the site of instantiation.
with function "=" (Left, Right : Func_Type) return Boolean is <>;
package Gen_Package is
function Check (Func : Func_Type) return Boolean;
end Gen_Package;
package body Gen_Package is
function Check (Func : Func_Type) return Boolean is
-- not constant because we cannot give an initialization expression.
-- if Func_Type is an access type, Null_Value will be initialized with null.
Null_Value : Func_Type;
begin
return Func = Null_Value;
end Check;
end Gen_Package;
您应该指定您需要的子程序访问类型作为您的形式参数。 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);
In generic packet will also be passed a function that accepts this type.
也许像
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;
?
如果没有关于您的意图的更多信息,很难提供帮助。通常,当您发现自己与类型系统作对时,这表明您存在设计问题。