我将从Ada中的一个通用过程的经典示例开始:
-------------------------
-- swaps.ads
-------------------------
package Swaps is
generic
type E is private;
procedure Generic_Swap (Left, Right : in out E);
end Swaps;-------------------------
-- swaps.adb
-------------------------
package body Swaps is
procedure Generic_Swap (Left, Right : in out E) is
Temporary : E;
begin
Temporary := Left;
Left := Right;
Right := Temporary;
end Generic_Swap;
end Swaps;现在,假设我想实现一个用于交换字符串的专用String_Swap过程,并将其提供给我的包的所有用户。我可以将以下内容添加到swaps.adb中的body声明中
procedure String_Swap is new Generic_Swap (String);但是,如果我没有向swaps.ads中的规范添加任何内容,那么没有一个包可以使用这个过程。例如:
-------------------------
-- main.adb
-------------------------
with Swaps; use Swaps;
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
First : String := "world!";
Second : String := "Hello, ";
begin
String_Swap (First, Second); -- #Error: String_Swap is undefined#
Put_Line (First);
Put_Line (Second);
end Main;我尝试将该过程的类型添加到规范中:
procedure String_Swap (Left, Right : in out String);但是Ada抱怨这个规范缺少一个主体,并且swaps.adb中的定义与它冲突。
发布于 2018-02-24 10:54:32
您不能将泛型用于String类型,因为它是一个无约束类型。但是,让我们使用Ada.Strings.Unbounded.Unbounded_String代替。
你要做的是:
with Ada.Strings.Unbounded;
package Swaps is
generic
type Element_Type is private;
procedure Generic_Swap (Left, Right : in out Element_Type);
procedure Swap (Left, Right : in out Ada.Strings.Unbounded.Unbounded_String);
end Swaps;package body Swaps is
procedure Generic_Swap (Left, Right : in out Element_Type) is
Temporary : Element_Type;
begin
Temporary := Left;
Left := Right;
Right := Temporary;
end Generic_Swap;
procedure Swap_Unbounded_Strings is
new Generic_Swap (Element_Type => Ada.Strings.Unbounded.Unbounded_String);
procedure Swap (Left, Right : in out Ada.Strings.Unbounded.Unbounded_String) is
begin
Swap_Unbounded_Strings (Left => Left,
Right => Right);
end Swap;
end Swaps;但总的来说,我更愿意将泛型的实例化与这些泛型的规范和实现完全分开。
发布于 2018-02-25 09:08:52
我解决这个问题的方法是使用一个子包:
with Ada.Strings.Unbounded;
package Swaps.Instances is
procedure Swap is new Generic_Swap (Element => Character);
procedure Swap is new Generic_Swap (Element => Ada.Strings.Unbounded.Unbounded_String;
...
end Swaps.Instances;请注意,可以编写一个处理不确定类型的泛型:
generic
type Element (<>) is private;并将Generic_Swap的主体更改为
procedure Generic_Swap (Left, Right : in out Element) is
Temp : constant Element := Left;
begin -- Generic_Swap
Left := Right;
Right := Temp;
end Generic_Swap;但是要使用它,实际对象必须是无约束的,或者具有相同的子类型。
发布于 2018-02-23 22:39:44
Swaps的用户唯一能看到的就是规范。由于规范中没有关于String_Swap的任何内容,所以包主体中的任何篡改都不会产生任何影响。
如果您希望“实现用于交换字符串的专用String_Swap过程”,则必须将其包括在规范中:
package Swaps is
generic
type E is private;
procedure Generic_Swap(Left, Right : in out E);
procedure String_Swap is new Generic_Swap(String);
end Swaps;这是一个糟糕的例子:当用-gnatl编译时,我们得到
1. package Swaps is
2. generic
3. type E is private;
4. procedure Generic_Swap(Left, Right : in out E);
5. procedure String_Swap is new Generic_Swap(String);
|
>>> actual for "E" must be a definite subtype
6. end Swaps;这是因为类型String是不确定的,也就是说,一个特定的String具有特定的长度,并且只能分配给另一个长度相同的String (或String的片段);因此,即使您的过程Main是在不使用泛型的情况下写出的,它在运行时也会失败,从而导致一个约束错误。看看Ada.Strings.Unbounded at ARM A.4.5。
所以,尝试一种明确的类型:
package Swaps is
generic
type E is private;
procedure Generic_Swap(Left, Right : in out E);
procedure Character_Swap is new Generic_Swap(Character);
end Swaps;不幸的是,
1. package Swaps is
2. generic
3. type E is private;
4. procedure Generic_Swap(Left, Right : in out E);
5. procedure Character_Swap is new Generic_Swap(Character);
|
>>> warning: cannot instantiate "Generic_Swap" before body seen
>>> warning: Program_Error will be raised at run time
6. end Swaps;解决方案必须是单独实例化:也许在库级别,
with Swaps;
procedure Character_Swap is new Swaps.Generic_Swap(Character);让您的用户根据自己的意愿实例化泛型会容易得多。
https://stackoverflow.com/questions/48956257
复制相似问题