adasubtype

In ada programming language, Is there a way to create a subtype which takes differently positioned enums of a type?


I am trying create a subtype which takes certain enumerations of a type for example,

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

I want something like this,

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

I understand that when we use the keyword subtype of a type we need to use range, but the problem is the enumeration is not in a series.


Solution

  • For this kind of values filtering, I would use subtype predicates.

    In your case, modifying your enumeration according to what Keith said :

    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;
    

    If you want to use numeric types instead of enumeration, use the following

    type Integers_Type is range 1 .. 10;
    
    subtype Odd_Numbers_Type is Integers_Type
       with Dynamic_Predicate => Odd_Numbers_Type mod 2 /= 0;
    
    

    For more information, you can read the rationale

    EDIT :

    For Enumeration types, the following compiles using gnatmake -gnata -gnatVa test_enum.adb but warns about the affectation line 14 and fails at execution because of the assert linked to the static predicate.

    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;
    

    For integer types, using the gnatmake -gnata -gnatVa test_int.adb compilation command, the compiler warns that the check will fail at runtime which is the case as the assertion is triggered.

    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;
    

    In both cases, removing the -gnata flag will make the program working without taking care of the predicate as asserts are desactivated.