我需要获取Ada枚举类型中某个值关联的数字值。不是枚举中的位置,而是在每个值上使用"for TYPE use"子句分配的值。
有人知道是否可能吗?
我需要获取Ada枚举类型中某个值关联的数字值。不是枚举中的位置,而是在每个值上使用"for TYPE use"子句分配的值。
有人知道是否可能吗?
目前还没有完全通用的解决方案。枚举表示子句似乎是设计成使得这些信息难以获得。(不过,Ada 2020将提供一种解决方案;有关详细信息,请参见本答案底部。)
以下内容:
function Rep is new Ada.Unchecked_Conversion(Enum, Integer);
这种方法在大多数情况下都可以使用,但是有一些严重的注意事项:表示值必须在 Integer'First..Integer'Last
范围内,如果 Enum
和 Integer
的大小不匹配,则结果实际上是实现定义的(但在 GNAT 中可行)。
正如 Simon Wright 所说,RM 推荐使用 Unchecked_Conversion
,但这并不是一个令人满意的解决方案,并且确定一致的目标类型很困难。
截至 2007 年 RM,推荐支持的级别为:
实现应支持至少 System.Min_Int..System.Max_Int 范围内的内部代码。
这意味着将其转换为 Integer
并不总是足够的;一个值可能小于 Integer'First
或大于 Integer'Last
。即使所有值都在该范围内,也没有真正好的方法来确定与枚举类型相同大小的目标类型。例如,下面的代码:
type Enum is (Ten, Twenty, Thirty);
for Enum use (10, 20, 30);
function Rep is new Ada.Unchecked_Conversion(Enum, Integer);
在GNAT中,会产生以下警告:
warning: types for unchecked conversion have different sizes
type Enum is (...);
for Enum use (...);
type Longest_Integer is range System.Min_Int .. System.Max_Int;
function Rep is new Ada.Unchecked_Conversion(Enum, Longest_Integer);
忽略警告。但编译器允许接受大于System.Max_Int值的值,只要它们在某个整数类型的范围内。例如,GNAT会拒绝此操作,但另一个Ada编译器可能会接受它:
type Longest_Unsigned is mod System.Max_Binary_Modulus;
type Unsigned_Enum is (Zero, Huge);
for Unsigned_Enum use (0, Longest_Unsigned'Last);
如果使用Unchecked_Conversion将此枚举类型转换为任何有符号整数类型,将无法正常工作。而且,如果大小不匹配,仍然存在实现定义结果的潜在问题。
以下是一种通用解决方案,适用于任何枚举类型,如果(a)表示值在System.Min_Int..System.Max_Int
范围内,且(b)如果Unchecked_Conversion
的实现比Ada标准要求的更好行为:
type Longest_Signed is range System.Min_Int .. System.Max_Int;
generic
type Enum is (<>);
function Generic_Rep(E: Enum) return Longest_Signed;
function Generic_Rep(E: Enum) return Longest_Signed is
function Rep is new Ada.Unchecked_Conversion(Enum, Longest_Signed);
begin
return Rep(E);
end Generic_Rep;
http://www.ada-auth.org/standards/2xrm/html/RM-13-4.html#p10.1
对于:
type MyEnum is (A, B, C);
我必须完成以下任务:
EVal : MyEnum := B;
IVal : Integer := MyEnum'Enum_Rep(EVal);
Value : Integer;
For Value'Address use ENUM_VAR'Address;
你需要使用抑制初始化的编译指示 pragma,尽管我现在无法回忆起它的名称。
如果我没记错的话,还有一种变体记录方法,可以将字段精确地叠加,并将记录用作视图转换。
pragma Import (Value, Ada);
,我想是这样的。 - Simon Wright据我理解,质量和风格指南中,枚举的内部表示值完全不需要考虑。经过大量研究,我曾决定使用以下结构:
type enum_c is (clk_eq, clk_div_2, clk_div_16, clk_div_128, clk_div_1024);
type enum_c_values is array (enum_c) of natural; -- or any type you wish
cdiv_values : constant enum_c_values := (
clk_eq => 1,
clk_div_2 => 2,
clk_div_16 => 16,
clk_div_128 => 128,
clk_div_1024 => 1024 );
c : enum_c := clk_div_128;
...
put_line("c =" & c'img & " natural value associated w/ c =" & cdiv_values(c)'img);
type Unsigned_Byte is new natural range 0 .. 255; for Unsigned_Byte'Size use 8; for Enum'Size use 8;
- user1818839type short_int is mod 2**enum_type'size;
- Jean-François Fabretype Enum is (Minus_One, Zero, One); for Enum use (-1, 0, 1);
- Keith Thompson