在ada编程语言中,是否有一种方法可以创建一个采用不同类型的枚举的子类型?

时间:2020-01-08 05:41:23

标签: ada subtype

我正在尝试创建一个子类型,该子类型例如需要某种类型的枚举,

type Integers_Type is (1,2,3,4,5,6,7,8,9,10);

我想要这样的东西

subtype Odd_Numbers_Type is Integers_Type (1,3,5,7,9);

我了解到,当我们使用一种类型的关键字subtype时,我们需要使用范围,但是问题是枚举不在序列中。

2 个答案:

答案 0 :(得分:7)

对于这种值过滤,我将使用subtype predicates

根据您的情况,根据Keith所说的修改枚举:

type Integers_Type is (ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN);

subtype Odd_Numbers_Type is Integers_Type 
   with Static_Predicate => Odd_Numbers_Type in ONE | THREE | FIVE | SEVEN | NINE;

如果要使用数字类型而不是枚举,请使用以下

type Integers_Type is range 1 .. 10;

subtype Odd_Numbers_Type is Integers_Type
   with Dynamic_Predicate => Odd_Numbers_Type mod 2 /= 0;

有关更多信息,您可以阅读the rationale

编辑:

对于枚举类型,以下代码使用 gnatmake -gnata -gnatVa test_enum.adb 进行编译,但警告第14行受影响,并且由于将断言附加到静态谓词而无法执行。

with Ada.Text_IO; use Ada.Text_IO;

Procedure Test_Enum is
   type Integers_Type is (ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN);

   subtype Odd_Numbers_Type is Integers_Type 
     with Static_Predicate => Odd_Numbers_Type in ONE | THREE | FIVE | SEVEN | NINE;

   Test_I : Integers_Type := TWO;
   Test_O : Odd_Numbers_Type := ONE;
begin
   Put_Line("Test_I=" & Integers_Type'Image (Test_I));
   Put_Line ("Test_O=" & Odd_Numbers_Type'Image (Test_O));
   Test_O := Test_I;
   Put_Line ("Test_O=" & Odd_Numbers_Type'Image (Test_O));
end Test_Enum;

对于整数类型,使用 gnatmake -gnata -gnatVa test_int.adb 编译命令,编译器会警告检查将在运行时失败,因为触发了断言。

with Ada.Text_IO; use Ada.Text_IO;

Procedure Test_Int is
   type Integers_Type is range 1 .. 10;

   subtype Odd_Numbers_Type is Integers_Type
     with Dynamic_Predicate => Odd_Numbers_Type mod 2 /= 0;

   Test_I : Integers_Type := 2;
   Test_O : Odd_Numbers_Type := 1;
begin
   Put_Line("Test_I=" & Integers_Type'Image (Test_I));
   Put_Line ("Test_O=" & Odd_Numbers_Type'Image (Test_O));
   Test_O := Test_I;
   Put_Line ("Test_O=" & Odd_Numbers_Type'Image (Test_O));
end Test_Int;

在这两种情况下,删除 -gnata 标志都会使程序正常运行,而无需考虑断言使断言无效的情况。

答案 1 :(得分:1)

您混淆了枚举和整数,如果您来自C之类,这是一个区别:在Ada中,枚举仅仅是整数的标签。

弗雷德里克·普拉卡(FrédéricPraca)给出的答案是绝对正确的,但是(a)您可以在数字类型上使用Static_Predicate; (b)有一种方法可以解决您在问题标题中提出的问题,而该问题与您在问题正文中提出的问题有细微差别。

使用子类型谓词的问题是您失去了使用某些谓词的能力

(a)— Static_Predicate

Type Digit_Range is 0..9;
Subtype Odd_Digit is Digit_Range
  with Static_Predicate => 1|3|5|7|9;

(b)-枚举的位置
在Ada中,有几个属性,其中包括PosVal,以及PredSucc。给定一个枚举(Type Example is (A,B,C,D,E);,您可以说Example'Pos(D)将返回3,也可以说Example'Val(1)将返回B

可以然后将事物组合在一起以创建多种类型,尽管这 是笨拙的,通常不是您想做的。

Type Base_Numeric_Range is range 0..9;
Type Odds is range 1..Base_Numeric_Range'Pos(Base_Numeric_Range'Last)) - Base_Numeric_Range'Pos(Base_Numeric_Range'First)) / 2;

-- This is from memory, and untested; so probably wrong in the details.
Function Convert(X : Base_Numeric_Range) return Odds is
        ( Odds'Val((Base_Numeric_Range'Pos(X) / 2) + 1) );
Function Convert(X : Odds) return Base_Numeric_Range is
        ( Base_Numeric_Range'Val(Odds'Pos(X) * 2 - 1) );