让我首先提供一些上下文,希望它能让问题更清楚:我正在从我希望操作的硬件接收字节向量数据。由于大小和时间限制,我不希望将日期转换为更大的大小。我想允许计算的中间值超出字节范围。这不是标量的问题(中间值保存在寄存器中,编译器不会为中间值发出约束错误)。
但是,在使用用户定义的运算符时,它更加棘手。我们可以将结果提升为更大的大小,但随后分配回原始类型将需要显式转换(子类型不能具有混合大小)。例如,在第 24 行下面的代码中将变为Z := To_Point((X + Y) / 2);
It is a solution,但我希望找到一个不需要添加“To_Point”功能的解决方案。
我在 Ada.Numerics 中查看了向量的实现,它使用的是实数值,并且不提升中间值,例如:
function "+" (Left, Right : Real_Vector) return Real_Vector;
这可能会导致约束错误,但与标量计算(取决于机器)相比,它更有可能导致一些准确性损失(因为实数的表示方式)。
1. pragma Ada_2012;
2. with Ada.Text_IO; use Ada.Text_IO;
3.
4. procedure Inter_Value is
5. type Byte is new Integer Range 0..255 with Size => 8;
6. A, B, C : Byte;
7.
8. type Point is array(1..2) of Byte with Convention => C, Size => 2*8;
9. X, Y, Z : Point;
10.
11. function "+" (Left, Right : Point) return Point is (Left (1) + Right (1), Left (2) + Right(2));
12. function "/" (Left : Point; Right : Byte) return Point is (Left (1) / Right, Left (2) / Right);
13.
14. begin
15. Put_Line(C'Size'Image);
16. A := 100;
17. B := 200;
18. C := (A + B) / 2; -- Ok, intermediate value in register
19. Put_Line("C = " & C'Image);
20.
21. Put_Line(X'Size'Image);
22. X := (100, 100);
23. Y := (200, 200);
24. Z := (X + Y) / 2; -- CONSTRAINT_ERROR, intermediate value in Point
25. Put_Line("Z = " & Z(1)'Image & Z(2)'Image);
26. end;