2

我需要一个相当复杂的计算结果来定义一个私有类型,如下所示:

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 能够满足这种需求(隐藏在所述包的主体中实例化包所需的复杂计算),如果它按照标准工作,我不会感到惊讶,但我不记得在任何地方读过类似的东西,并想知道确切的规则。

4

2 回答 2

1

编辑,反映解释为什么reallyComplicatedFunction不应该公开的评论。

如果我理解正确,该功能实际上并不依赖于Mystic,而reallyComplicatedFunction应该是私有的。在这种情况下,我会尝试将其放在其他地方,并保持对top_m. 我假设它Table也可以被移动,即使它正式创建一个依赖于reallyComplicatedFunction,Table在它的参数配置文件中。为了解决这个问题,在层次结构中创建了一个新的私有位置,一个私有兄弟获得声明,并且只会在 original 的私有部分中使用Mystic。因此,private with在后者的上下文条款中。

package Top is end;

private generic
    top_m : Positive;
package Top.Outsourced is

    type Table is array (Positive range <>) of Positive;
    function reallyComplicatedFunction(x : Positive) return Table;

end Top.Outsourced;

private with Top.Outsourced;
generic
    Top_M : Positive;
package Top.Mystic is
    type T is private;
private
    package Initializer is new Top.Outsourced (top_m);
    subtype Table is Initializer.Table;

    mytable : constant Table := Initializer.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 Top.Mystic;


package body Top.Outsourced is

    function reallyComplicatedFunction(x : Positive) return Table is
        Limit : Positive;
    begin
        Limit := Positive'Min (top_m, 1) + x/2;
        return Result : Table (1 .. Limit);
    end reallyComplicatedFunction;

end Top.Outsourced;
于 2017-04-12T06:02:09.513 回答
0

假设(因为您没有指定它)从返回的数组reallyComplicatedFunction具有 range 1..top_m,您可以定义一个新的子类型并将其用作两个数组的范围:

subtype My_Range is Positive range 1..m_top
type Table is array (My_Range) of Positive;

type T is array (My_Range) of Natural;

并在包体内my_table移动。reallyComplicatedFunction

于 2017-04-11T16:00:02.043 回答