Get value of enum type representation in Ada

I need to get a numeric value associated with an ena type value in Ada. Not a position in the enumeration, but the value assigned to the condition "to use TYPE" for each value.

Does anyone know if this is possible?

+7
source share
6 answers

There is no general solution. The presentation of the enumeration view is apparently intended to make it difficult to obtain this information.

It:

function Rep is new Ada.Unchecked_Conversion(Enum, Integer); 

most likely it will work in most cases, but there are some serious caveats: the view values ​​should be within the range of Integer'First..Integer'Last , and if the sizes of Enum and Integer do not match the result, the implementation is actually implemented (but it works with GNAT )

According to Simon Wright, RM recommends Unchecked_Conversion , but this is not a very satisfactory solution, and determining a consistent target type is difficult.

Since 2007, the recommended support level:

An implementation must support at least internal codes in the range System.Min_Int..System.Max_Int.

which means that converting to Integer not always enough; the value may be less than Integer'First or greater than Integer'Last . And even if all values ​​are in this range, there is no really good way to determine the target type of the same size as the enumeration type. For example, this:

 type Enum is (Ten, Twenty, Thirty); for Enum use (10, 20, 30); function Rep is new Ada.Unchecked_Conversion(Enum, Integer); 

displays this warning in GNAT:

 warning: types for unchecked conversion have different sizes 

But after a warning, Rep returns the expected values ​​of 10, 20, and 30.

RM explicitly states that if the source and target sizes in an Unchecked_Conversion instance do not match, and the result type is scalar, then

the result of the function is determined by the implementation and may have an invalid representation

Thus, the fact that the above works for GNAT does not mean that it is guaranteed to work everywhere.

For an implementation that only supports values ​​in the range System.Min_Int..System.Max_Int , you can do something like this:

 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); 

and ignore the warning. But compilers are allowed to accept values ​​that exceed System.Max_Int if they are in the range of some integer type. For example, GNAT rejects this, but another Ada compiler may accept it:

 type Longest_Unsigned is mod System.Max_Binary_Modulus; type Unsigned_Enum is (Zero, Huge); for Unsigned_Enum use (0, Longest_Unsigned'Last); 

and Unchecked_Conversion from this to any signed integer type will not work. And you still have the potential problem of implementing certain results if the sizes do not match.

Here's a general solution that should work for any type of enumeration if (a) the view values ​​are in the range System.Min_Int..System.Max_Int and (b) if it is better to implement Unchecked_Conversion behavior than the Ada standard, be:

 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; 

Given all this confusion, you might consider using some kind of mechanism other than listing submission suggestions to do whatever you are trying to do.

+8
source

If you use GNAT and do not mind the compiler, this compiler provides an attribute for this

+5
source

AARM 13.4 (para 11/1) recommends Unchecked_Conversion (to, possibly, Integer).

+2
source

If you are not using JVM or .NET compilers, you can overlay them in two; something like:

 Value : Integer; For Value'Address use ENUM_VAR'Address; 

You will want to use a pragma that suppresses initialization, although I do not remember it at the moment.

IIRC. There is also a recording options method where you can precisely overlay fields and use the recording as a kind of view transformation.

+1
source

since I understand the manual on quality and style, we should not forget about the internal meanings of the presentation of enumerations. after a lot of research, I once decided to use the following construction:

 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); 
+1
source

What I found to work in GNAT for:

 type MyEnum is (A, B, C); 

I had to do:

 EVal : MyEnum := B; IVal : Integer := MyEnum'Enum_Rep(EVal); 
0
source

All Articles