我需要一个相当复杂的计算结果来定义一个私有类型,如下所示:
generic
top_m : Positive;
package Mystic is
type T is private;
private
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
mytable : constant Table := reallyComplicatedFunction(top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Mystic;
我需要类型 T 以一种非常复杂的方式依赖泛型参数 top_m,由 realComplicatedFunction(.) 体现。该函数在包 Mystic 的主体中定义,但它不使用包声明的任何其他内容。
令我惊讶的是,这个设置工作得很好。也许我很幸运,因为据我对 ARM 的解密可以看出,这种函数调用仅仅是“合法的”,但不能保证不会抛出 Program_Error。我将其解释为“完全禁止这类东西过于严格,但也不能指望编译器在所有情况下都确定其可行性,因此我们只允许您进行试验”。然后有很大的可能性是我完全误读了参考手册。无论如何,关于 Ada 的书籍对这类事情给出了相当严厉的警告,通常是围绕 pragma Elaborate 等人的讨论,所以我几乎没有尝试这个解决方案。
我还尝试将该函数放在 Mystic 的私有子包中,但我无法根据父级和父级规范隐含地解决子级之间的循环,具体取决于子级。无论如何,这个函数不是 Mystic 的扩展,而是初始化它的必要代码。
那么我的问题是:这种功能的合适位置在哪里?
ETA:应 Simon Wright 的要求,这是我遇到的 ARM 部分:http: //www.ada-auth.org/standards/12rm/html/RM-3-11.html entries 9, 10/1和 14:
对于尝试使用主体的构造,将执行检查 (Elaboration_Check),如下所示:
- 对于对具有显式主体的(未受保护的)子程序的调用,将检查主体是否已详细说明。此检查和调用的任何实际参数的评估以任意顺序完成。
...
如果这些检查中的任何一个失败,则会引发异常 Program_Error。
据我了解,构造 mytable : constant Table := etc. 尝试使用 realComplicatedFunction 的主体,因此它必须检查它是否被详细说明。我假设-这是我推理中的一个弱点,但这是我的理解-reallyComplicatedFunction 主体的详细说明仅发生在 Mystic 包主体的详细说明期间,因此我的功能不会在当时详细说明从包规范的私有部分调用。尽管如此,在使用包(的实例)时,我没有收到承诺的 Program_Error 。
ETA2:根据trashgod 的评论,我尝试将包Mystic 变成非通用包;将 top_m 设为可见常量并删除通用部分。编译器现在捕捉到了我从一开始就担心的循环性,程序以 Program_Error: access before elaboration 退出。就好像在第一次实例化之前,或者更确切地说,在实例化期间详细说明所述包的规范之前,对通用包的主体进行了详细说明。由于我希望 Ada 能够满足这种需求(隐藏在所述包的主体中实例化包所需的复杂计算),如果它按照标准工作,我不会感到惊讶,但我不记得在任何地方读过类似的东西,并想知道确切的规则。