我知道在基类型的约束子类型的赋值中,如果我不确保该值在赋值之前的范围内,那么我在运行时会遇到Range_Check异常的风险。
但是在进行比较时是否也是如此?我认为,由于用户想要的唯一知识是布尔结果,因此不需要隐式转换为基本类型或范围检查。
请注意:我正在寻找引用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;
我还没有找到完整的答案。但我确实找到了几个有趣的数据。
离散类型的操作 / 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不满足目标子类型的约束。
这似乎表明隐式类型转换将始终执行到子类型(我很难阅读该语言)。但我没有看到任何声明在子类型和基本类型之间进行比较的地方。
我也对声明感到困惑:
执行隐式子类型转换以调整操作数的数组边界(如果有)以匹配所需的目标子类型
Ada95 Rationale - Part I Overview - 这太高了。这里没什么用的。
Ada95 Rationale - Part II - 3.1 Types, Classes, Objects and Views - 此部分提供了大量有关类型的深刻信息,但仍然与比较类型和子类型无关
我可能在搜索中错过了答案。但我正在寻找这种或那种方式的明确证据。
很抱歉阅读不久。
答案 0 :(得分:7)
您可能会发现带注释的ARM版本(AARM95 3.2)很有帮助(请注意,您的引用是针对未维护的AdaHome网站;更喜欢http://www.adaic.org)。
子类型具有类型和可能的约束:
type T is ...;
subtype S1 is T; -- effectively a renaming of T
subtype S2 is T range ...; -- (added) constraints
并且子类型的操作是其类型的操作,这就是为什么你可以在没有转换的情况下编写比较Day = Payday
的原因。我们知道Workday_Type
是Day_Type
,因此我们可以直接进行比较。
Workday_Type (Day) = Payday
确实存在CE风险,但您或编译器无需这样做。
答案 1 :(得分:1)
就像Simon Wright has explained一样,操作是类型的操作,而子类型形成类型值的子集,而不是具有不同操作的不同类型。
为了便于说明,请考虑"+"
:
type N is range 0 .. 10;
X : constant N := N'Base'(-1) + N'(2);
许多Ada规则适用,而IANALL,我记得LLawyers强调规则的制定是为了在不引起异常的情况下产生数学上(逻辑上)正确的结果,即使看起来某些操作涉及超出范围的值一路上。 LRM 4.5中有一个提示。所以,我希望relational_operator
规则,特别是"="
,也是支持性的。