为什么 Ada 没有捕获这个指定的范围检查?

hyp*_*use 11 ada

我正在阅读 learn.adacore.com 教程,但遇到了一个我不确定的问题。

具体来说,我知道 Ada 旨在捕获试图溢出具有指定范围定义的变量的尝试。

在下面的情况下,第一次尝试这样做会导致编译器“范围检查失败”,这是预期的。但是以下行并没有捕获它,我不知道为什么:

with Ada.Text_IO; use Ada.Text_IO;

procedure Custom_Floating_Types is
    type T_Norm is new float range -1.0 .. 1.0;

    D : T_Norm := 1.0;
begin
    Put_Line("The value of D =" & T_Norm'Image(D));
    -- D := D + 1.0; -- This causes a range check failure at run time = completely expected.
    Put_Line("The value of D =" & T_Norm'Image(D + 1.0)); -- This doesn't?

end Custom_Floating_Types;
Run Code Online (Sandbox Code Playgroud)

Jef*_*ter 11

您有几个很好的答案,但我将添加另一个,因为很明显您希望表达式D + 1.0引发异常,而您的答案没有解释为什么不会。

像这样的类型声明

type T_Norm is new float range -1.0 .. 1.0;
Run Code Online (Sandbox Code Playgroud)

大致相当于

type T_Norm'Base is new Float;
subtype T_Norm is T_Norm'Base range -1.0 .. 1.0;
Run Code Online (Sandbox Code Playgroud)

类型(称为“基本类型”)没有命名,尽管它通常可以用'Base属性引用。给出的名称是一个子类型,称为“第一个命名的子类型”。

这种区别很重要,但往往没有得到足够的重视。正如 egilhh 所解释的那样,T_Norm'Image是根据 定义的T_Norm'Base。算术运算符也是如此。例如,"+"定义为

function "+" (Left : in T_Norm'Base; Right : in T_Norm'Base) return T_Norm'Base;
Run Code Online (Sandbox Code Playgroud)

2.0 显然在 的范围内T_Norm'Base,因此评估D + 1.0不会违反任何约束,也不会将其传递给T_Norm'Image。但是,当您尝试将结果值分配给D具有 subtype 的 时T_Norm,将执行检查该值是否在子类型的范围内,并且由于检查失败而引发异常。

这种区别在其他地方使用,使语言可以合理地工作。例如,一个受约束的数组类型

type A is array (1 .. 10) of C;
Run Code Online (Sandbox Code Playgroud)

大致相当于

type A'Base is array (Integer range <>) of C;
subtype A is A'Base (1 .. 10);
Run Code Online (Sandbox Code Playgroud)

如果你这样做

V : A;
... V (2 .. 4)
Run Code Online (Sandbox Code Playgroud)

您可能会遇到问题,因为切片没有A. 但它有效,因为切片没有子类型A,而是匿名子类型A'Base (2 ..4)


egi*_*lhh 7

'图像的定义说:

对于每个标量子类型 S:

S'Image 表示具有以下规范的函数:

函数 S'Image(Arg : S'Base) 返回字符串

如您所见,它接受一个基本(无约束)类型的参数