Ada:子类型转换或调用“Base”

Ada: Subtype Conversion or calling 'Base

我有以下 - 简单 - 问题:表示度数的增量类型及其子类型,角度,我将范围限制在 0.0 .. <360.0 之间。 现在,我想覆盖子类型的“+”运算符以拥有我自己的模运算符:

package ...
type Degree is digits Degree_Digits;
end package

package ...
subtype Limited_Angle is Degree range Degree_Min .. Degree_Max;
function "+" (Left, Right : in Limited_Angle) return Limited_Angle;
end package

和实施:

function "+" (Left, Right : in Limited_Angle) return Limited_Angle is
    res : Degree;
begin
    res := Units.Base.Degrees."+"(Left, Right);
    ...
    return Limited_Angle(res);
end "+";

但我不喜欢调用 +-运算符的方式。我的第一个想法是

res := Degree(Left) + Degree(Right);

但这不起作用。我的编译器警告无限递归。 甚至更严格:

res := (Degree(Left)) + (Degree(Right));

警告无限递归。我不明白这背后的原理。 T(S) 不应该将 S 转换为 T 吗?它不可能是优化问题,因为 (T(S)) 也不起作用。

我是否误解了类型-子类型转换的概念(很可能),有人有 solution/explanation 吗?或者更好的解决方案?

谢谢!

目前没有可用的编译器,因此未测试,但是

res := Units.Base.Degrees."+"(Left, Right);

是可疑的,因为您不需要为 leftright 指定运算符 "+",它们是 Limited_Angle。所以我想知道上面的行是否正在调用当前的 "+" 运算符(因此是递归的)?

我会看看是否写:

function "+" (Left, Right : in Degree) return Limited_Angle 

是一个更好的选择,因为您可以在对 Limited_Angle 取模之前在 Degree 中进行 "+" 数学计算。这也将节省您随叫随到的演员阵容。

您的问题与类型转换无关,而是与理解类型和子类型之间的区别有关。

一个类型的所有子类型都具有完全相同的操作。类型的子类型(包括类型本身,技术上 "first subtype of the type")之间的差异只是允许值的集合。

这意味着你在 DegreesLimited_Degrees 之间的所有转换都没有做太多,你对 Units.Base.Degrees."+" (Left, Right) 的调用实际上是一个递归调用。

我认为您的问题的解决方案是使 Limited_Degrees 成为派生类型,而不是子类型。