当比较Ada Scalar类型和受约束的子类型时,我是否需要进行范围检查?
我知道在从基类型赋值给受约束的子类型时,如果我不确保该值在赋值之前在范围内,那么我在运行时会遇到Range_Check异常的风险 .
但是在进行比较时这也是正确的吗?我认为,由于用户想要的唯一知识是布尔结果,因此不需要隐式转换为基本类型或范围检查 .
Please Note :我正在寻找引用Ada95 LRM的答案 .
示例
declare
type Day_Type is (SUN, MON, TUE, WED, THU, FRI, SAT);
subtype Workday_Type is MON .. FRI;
Payday : constant Workday_Type := FRI;
...
function Is_Payday (Day : Day_Type)
return Boolean is
begin
return (Day = Payday);
end Is_Payday;
begin
-- Will this raise a RANGE_CHECK error in Is_Payday()?
if Is_Payday(Day => SAT) then
...
elsif Is_Payday(Day => FRI) then
...
end if;
end;
到目前为止我发现了什么......
我还没有找到完整的答案 . 但我确实找到了几个有趣的数据 .
Operations of Discrete Types / Chapter 3.5.5 para 12它说:
-
3.2 Types and Subtypes - 本章仅讨论如何定义类型和子类型 .
-
3.5.5 Operations of Discrete Types - 本章中有一个有趣的注释,但我不确定本章或其他任何内容是否相关 .
(31)对于离散型的子类型,属性Val传递的结果可能不属于子类型;类似地,属性Pos的实际参数不必属于子类型 . 通过以下属性满足以下关系(在没有例外的情况下):S'Val(S'Pos(X))= X
S'Pos(S'Val(N))= N.
-
4.5.1 Logical Operators and Short Circuit Control Forms - 这里没有关于类型与子类型的内容 .
-
4.6 Type Conversions - 现在,我认为这是一个很好的答案 . 但它并没有跳出来 . 我在note (20)看到了一个小线索 .
(20)除了显式的type_conversions之外,类型转换是在构造的预期类型和实际类型不同的情况下隐式执行的,如类型解析规则允许的那样(见8.6) . 例如,整数文字的类型为universal_integer,并在分配给某个特定整数类型的目标时进行隐式转换 . 类似地,当相应的形式参数是类范围类型时,隐式转换特定标记类型的实际参数 . 即使预期和实际类型相同,也会执行隐式子类型转换以调整操作数的数组边界(如果有)以匹配所需的目标子类型,或者如果(可能已调整的)值不满足,则引发Constraint_Error目标子类型的约束 .
这似乎表明隐式类型转换将始终执行到子类型(我很难阅读该语言) . 但我没有看到任何声明在所需的子类型和基类型之间进行比较的地方 .
我也对声明感到困惑:
执行隐式子类型转换以调整操作数的数组边界(如果有)以匹配所需的目标子类型
-
Array Bounds是否引用数组类型?或者是否引用了受约束子类型的范围?
-
如果没有子类型,是否有目标子类型?
Ada 95理由......
-
Ada95 Rationale - Part I Overview - 这太高了 . 这里没什么好帮的 .
-
Ada95 Rationale - Part II - 3.1 Types, Classes, Objects and Views - 此部分有很多关于类型的深刻信息,但仍然与比较类型和子类型无关
我可能在搜索中错过了答案 . 但我正在寻找这种或那种方式的明确证据 .
很抱歉长时间阅读 .
2 回答
您可能会发现Annotated ARM版本(AARM95 3.2)很有帮助(请注意,您的引用是针对未维护的AdaHome网站;更喜欢http://www.adaic.org) .
子类型具有类型和可能的约束:
并且子类型的操作是其类型的操作,这就是为什么你可以在没有转换的情况下编写比较
Day = Payday
的原因 . 我们知道Workday_Type
是Day_Type
,所以我们可以直接进行比较 .确实,
Workday_Type (Day) = Payday
存在CE的风险,但您或编译器不需要这样做 .就像Simon Wright has explained一样,操作是一种类型的操作,而 subtype 形成一种类型的值的子集,而不是具有不同操作的不同类型 .
为了便于说明,请考虑
"+"
:许多Ada规则适用,而IANALL,我记得LLawyers强调规则的制定是为了在不引起异常的情况下产生数学上(逻辑上)正确的结果,即使看起来某些操作涉及的值超出范围 . LRM 4.5中有一个提示 . 所以,我期待
relational_operator
规则,特别是"="
,也是支持性的 .