Generics 如何使用子包/泛型包实例化中的类型

Generics 如何使用子包/泛型包实例化中的类型,generics,ada,Generics,Ada,我可以使用 像这样使用所有类型: package Type_Package is type T is null record; procedure Action(X: T) is null; end Type_Package; with Type_Package; procedure Use_Type is use all type Type_Package.T; X: Type_Package.T; begin Action(X); end Use_Type;

我可以使用
像这样使用所有类型

package Type_Package is
   type T is null record;
   procedure Action(X: T) is null;
end Type_Package;

with Type_Package;
procedure Use_Type is
   use all type Type_Package.T;
   X: Type_Package.T;
begin
   Action(X);
end Use_Type;
 1. procedure B840003 is
 2. begin
 3.
 4.    declare
 5.       package Pkg_1 is
 6.          type Enum is (Aaa, Bbb, Ccc);
 7.          procedure Prim_Proc (X : Enum := Aaa) is null;
 8.          function Prim_Func return Enum is (Bbb);
 9.
10.          package Nested is
11.             procedure Nonprim_Proc (X : Enum := Bbb) is null;
12.             function Nonprim_Func return Enum is (Ccc);
13.          end Nested;
14.
15.       end Pkg_1;
16.
17.    begin
18.       declare
19.          use all type Pkg_1.Enum;
20.       begin
21.          if Prim_Func /= Bbb then                                  -- OK.
22.             null;
23.          end if;
24.          if Nonprim_Func (Ccc) /= Ccc then                         -- ERROR:
                |
    >>> "Nonprim_Func" is not visible
    >>> non-visible declaration at line 12

25.             null;
26.          end if;
27.          Prim_Proc;                                                -- OK.
28.          Nonprim_Proc (Aaa);                                       -- ERROR:
             |
    >>> "Nonprim_Proc" is not visible
    >>> non-visible declaration at line 11

29.       end;
30.    end;
31.
32. end B840003;
但是,当我将
Type_Package
移到内部时,它似乎不起作用
使用类型

procedure Use_Type is
   package Type_Package is
      type T is null record;
      procedure Action(X: T) is null;
   end Type_Package;
   use all type Type_Package.T;
   X: Type_Package.T;
begin
   Action(X);
end Use_Type;
我明白了

当我实例化一个泛型包时,也会发生同样的事情。对于 例如,当我想使用
Ada.Containers
中的数据类型时

package Element_Set is
   new Ada.Containers.Hashed_Sets(Element_Type, Hash, "=");
use all type Element_Set.Set;
这里的
use type
子句似乎没有效果

在子包或子包中声明类型时如何使用该类型 通用包的实例化?

我不确定这是编译器错误(更新:Simon Wright确认它是错误)还是有意的,但您的解决方案包括:

对整个软件包使用“Use Type_Package”——可能是最简单但最繁重的一种

使用一些过程/函数重命名子句-这需要更多的工作,但不会使整个包可见。例如:

过程Hello是 包类型\u包为 类型T为空记录; 程序动作(X:T)为空; 端型包装; 使用所有类型的包装; X:Type_Package.T; 程序操作(X:Type_Package.T)重命名Type_Package.Action; 开始 行动(X); 结束问候; 对于泛型包,在库级别声明它们-这对嵌套包没有帮助,但对泛型包有帮助。您可以对单个泛型包执行以下操作:

类型_Package.ads

使用所有类型;
包装类型\包装是新使用的\所有\类型;
使用所有类型的广告

通用
包使用所有类型为
类型T为空记录;
程序动作(X:T)为空;
所有类型的最终用途;
或对于多个通用软件包:

类型_Package.ads

使用所有类型;
包类型\u包为
机组UAT为新用途全自动型;
T亚型为UAT.T;
使用所有类型的UAT.T;
--对其他泛型重复上述步骤
端型包装;
使用所有类型的广告

通用
包使用所有类型为
类型T为空记录;
程序动作(X:T)为空;
所有类型的最终用途;
这两种方法都适用于以下主要方面:

带有类型_包;
主要程序是
使用所有类型的包装;
X:Type_Package.T;
开始
行动(X);
端干管;

旁注:如果在这里没有人明确回答这是不是有意的,你可以考虑发送AdACOR错误报告。

< p>你确实发现了编译器错误。

有一组测试(ACAT-也是),其中“B系列”设计用于检查编译器是否捕获错误

其中一个测试从您的问题开始:一个精简和稍微修改的版本的行为如下:

package Type_Package is
   type T is null record;
   procedure Action(X: T) is null;
end Type_Package;

with Type_Package;
procedure Use_Type is
   use all type Type_Package.T;
   X: Type_Package.T;
begin
   Action(X);
end Use_Type;
 1. procedure B840003 is
 2. begin
 3.
 4.    declare
 5.       package Pkg_1 is
 6.          type Enum is (Aaa, Bbb, Ccc);
 7.          procedure Prim_Proc (X : Enum := Aaa) is null;
 8.          function Prim_Func return Enum is (Bbb);
 9.
10.          package Nested is
11.             procedure Nonprim_Proc (X : Enum := Bbb) is null;
12.             function Nonprim_Func return Enum is (Ccc);
13.          end Nested;
14.
15.       end Pkg_1;
16.
17.    begin
18.       declare
19.          use all type Pkg_1.Enum;
20.       begin
21.          if Prim_Func /= Bbb then                                  -- OK.
22.             null;
23.          end if;
24.          if Nonprim_Func (Ccc) /= Ccc then                         -- ERROR:
                |
    >>> "Nonprim_Func" is not visible
    >>> non-visible declaration at line 12

25.             null;
26.          end if;
27.          Prim_Proc;                                                -- OK.
28.          Nonprim_Proc (Aaa);                                       -- ERROR:
             |
    >>> "Nonprim_Proc" is not visible
    >>> non-visible declaration at line 11

29.       end;
30.    end;
31.
32. end B840003;
(参见第27行)而与您的示例更相似的一个示例(将包声明拉到子程序的声明区域)则执行以下操作:

 1. procedure B840003_Mod is
 2.    package Pkg_1 is
 3.       type Enum is (Aaa, Bbb, Ccc);
 4.       procedure Prim_Proc (X : Enum := Aaa) is null;
 5.       function Prim_Func return Enum is (Bbb);
 6.
 7.       package Nested is
 8.          procedure Nonprim_Proc (X : Enum := Bbb) is null;
 9.          function Nonprim_Func return Enum is (Ccc);
10.       end Nested;
11.
12.    end Pkg_1;
13.
14.    use all type Pkg_1.Enum;
15. begin
16.    if Prim_Func /= Bbb then                                  -- OK.
17.       null;
18.    end if;
19.    if Nonprim_Func (Ccc) /= Ccc then                         -- ERROR:
          |
    >>> "Nonprim_Func" is not visible
    >>> non-visible declaration at line 9

20.       null;
21.    end if;
22.    Prim_Proc;                                                -- OK.
       |
    >>> "Prim_Proc" is not visible
    >>> non-visible declaration at line 4

23.    Nonprim_Proc (Aaa);                                       -- ERROR:
       |
    >>> "Nonprim_Proc" is not visible
    >>> non-visible declaration at line 8

24.
25. end B840003_Mod;
参见第22行(过程调用;第16行的函数调用是可以的!)

这值得向AdaCore报告一个bug(尽管我不希望他们放弃所有东西并匆忙修复它)



有趣的是,早期版本的编译器(如GNAT CE 2018)发现
Bbb
Ccc
不可见。

我想知道第二个示例中的问题是否是
Type\u包
不在库级别?(顺便说一下,它不是子包;
Containers
Ada.Containers
中的子包).另一方面,并不是说包必须在库级别-?只说
使用Type\u package;
@SimonWright是的,
Type\u package
在第二个示例中不在库级别。我想知道为什么
使用Type
似乎只有在库级别时才起作用。而实例化库级别的泛型包。当我说子包时,我的意思是
Type\u-package
Use\u-Type
的声明部分声明。正确的术语是什么?使用整个包是可行的,但我很好奇如何只使用一个类型。@SimonWright在后一种情况下,编译器几乎不可用将操作视为T类型的基本操作。如果我举个例子并添加一个“=”操作,它会发现“使用所有类型”很好。我在RM中找不到任何可以清除此操作的内容。我觉得这样做应该是合法的,但只是一种感觉。