我正在尝试创建一个具有默认值的子程序参数的Ada通用包 . 我不能让编译器识别默认值..我猜这是由于可见性 . 有没有办法在泛型声明中转发声明一个函数?
通用规格:
generic
type Item is private;
type Item_Ref is access all Item;
Addr : System.Address;
Default : Item;
with Is_Valid (Obj : Item) return Boolean;
-- Forward Declare ** DOES NOT COMPILE
function Default_Validate (Data_Ptr : Item_Ref) return Boolean;
with function Validate (Data_Ptr : Item_Ref) return Boolean is Default_Validate;
package Foo is
-- function Default_Validate (Data_Ptr : Item_Ref) return Boolean;
function Read_Eeprom return Item;
end Foo;
通用机构:
package body Foo is
Obj : aliased Item;
for Obj'Address use Addr;
-- Read Method
function Read_Eeprom return Item is
begin
-- ** Read EEPROM using OBJ **
Validate (Obj'Unchecked_Access);
end Read_Eeprom;
-- Default Validate Method
function Default_Validate (Data_Ptr : Item_Ref) return Boolean is
Valid : Boolean;
begin
Valid := Is_Valid(Data_Ptr.all);
if not Valid then
Data_Ptr.all := Default;
end if;
return Valid;
end Default_Validate;
end Foo;
司机
with Foo;
procedure Main is
MAX_INT : constant Integer := 100;
MIN_INT : constant Integer := 0;
-- Special / Non-Scaler Type
type Pair_Type is
record
X : Integer;
Y : Integer;
end record;
type Pair_Ref is access all Pair;
-- Is Valid
function Int_Is_Valid(Int : Integer) return Boolean is
begin
return (Int <= MAX_INT and Int >= MIN_INT);
end Pair_Is_Valid;
-- Is Valid
function Pair_Is_Valid(Pair : Pair_Type) return Boolean is
begin
return Pair.X'Valid and Pair.Y'Valid;
end Pair_Is_Valid;
-- Validate
function Pair_Validate(Pair : Pair_Ref) return Boolean is
Valid : Boolean := True;
begin
if not Pair.X'Valid then
Pair.X := 0;
Valid := False;
end if;
if not Pair.Y'Valid then
Pair.Y := 0;
Valid := False;
end if;
return Valid;
end Special_Validate;
type Int_Ref is access all Integer;
My_Int : Integer;
My_Pair : Pair_Type;
Default_Pair : Pair_Type := (0,0);
package Int_Obj is new Foo (Item => Integer,
Item_Ref => Int_Ref,
Addr => My_Int'Address,
Default => 0,
Is_Valid => Int_Is_Valid);
package Pair_Obj is new Foo (Item => Pair_Type,
Item_Ref => Pair_Ref,
Addr => My_Pair'Address,
Default => Default_Pair,
Is_Valid => Pair_Is_Valid,
Validate => Pair_Validate);
Tmp_Int : Integer;
Tmps_Pair : Pair_Type;
begin
Tmp_Int := Int_Obj.Read_Eeprom;
Tmp_Pair := Pair_Obj.Read_Eeprom;
end Main;
我得到的错误是“预期文件结束,文件只能有一个编译单元”如何将通用子程序默认为作为包的成员的函数?
4 回答
不幸的是,你可以解决一个鸡蛋问题 . 编译器需要弄清楚所有通用参数在实例化泛型之前会是什么;但是,在实例化泛型之后,
Default_Validate
方法才会可用 . 我认为你最接近的是声明两个泛型:(我还没有测试过这个 . 测试好了 . 编译好 . )我假设Foo中唯一公开可见的东西是程序和功能 . 如果还有其他重要功能(例如类型),它会变得更复杂,然后您可能必须使用嵌套泛型,其中
with function Validate
从外部泛型移动到内部泛型,或者您可能能够使用通用正式包将通用分为两部分 . 在任何一种情况下,泛型的用户可能必须执行两个实例化 . 如果上述解决方案有效,那么用户将实例化Foo
或Foo_With_Default_Validator
,但它将是一个或另一个 - 两个实例不需要查看Foo
的可见部分 .EDIT 2: 这里's a solution if you'在实例化时需要
'Access
属性:然后在
Foo
的正文中,你需要一个这样的函数:每当你想调用验证函数时,从身体的其余部分调用
Perform_Validate
. (Perform_Validate
可以使用新的Ada 2012功能更简洁地编写,但你明白了 . )正如您所知,泛型定义了一个函数
Default_Validate
,因为关键字 function 前面没有 with . 你应该拥有的是:EDIT:
评论澄清说,以前不是你想要的 . 上面的表单将用于你有一个可能重写的验证器和一个默认的不必使用标记类型(Ada的OOP类实例的术语)的情况 .
相反,你想要的是参数可能从可见的子程序中获取子程序作为形式参数的默认值,以下是这样的:
但即使这样也可能会有所改善:
这可能是解决这个问题的最好方法;你进入/退出你的系统应该得到验证;例如文件读取,数据库读取,用户输入等)
嗯,有一种方法可以想到 . 它要求我们限制我们在通用中接受的内容 . 我的其他解决方案[几乎]完全概括,因此适用于任何非限制类型 .
取
'Valid
属性,我们看到documentation这样说:The Valid attribute can be used to check the validity of data produced by unchecked conversion, input, interface to foreign languages, and the like.
所以我们有一个默认的验证 .
我们还有一种方法可以将属性置于函数形式参数的默认值中 .
我们有一种默认可见功能的方法 .
最后我们有嵌套泛型 .
现在没有通用的正式类型
scalar
,这在这里很有用......但是我们有办法限制形式参数的类型Type T(<>) is (<>)
仅限于整数数字,模块类型和枚举...我们都知道是标量类型 .使用这些包将如下:
如果您很乐意将形式参数限制为积分/模块/枚举,那么这应该可行 .
所以,你去吧 .
推荐阅读:
Ada的通用形式系统
没有语法突出显示,因为它看起来很糟糕 .
你真的继续移动球门柱 . 总而言之,你的新增功能是可怕的:它们根本不编译,而且它们是一些明显剪切和粘贴的代码,如下所示:不匹配的函数名称(例如
Int_Is_Valid
/Pair_Is_Valid
) .首先,让我们使用签名包 .
signature.ads
foo.ads
foo.adb
driver.ads
driver.adb
鉴于围绕
access
-types的代码结构非常明显,如果您尝试使用Ada,那么我将会给您带来很多麻烦/工作,就像它是C风格的语言一样 .此外,坐下来,深吸一口气,思考问题空间和建筑物也可能是有益的 .