From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,45a9122ddf5fcf5 X-Google-Attributes: gid103376,public From: mheaney@ni.net (Matthew Heaney) Subject: Re: Valid Attribute and Unchecked Conversion Date: 1996/10/04 Message-ID: #1/1 X-Deja-AN: 187489164 references: <1996Oct1.100608.1@eisner> content-type: text/plain; charset=ISO-8859-1 organization: Estormza Software mime-version: 1.0 newsgroups: comp.lang.ada Date: 1996-10-04T00:00:00+00:00 List-Id: In article , kst@thomsoft.com (Keith Thompson) wrote: >So, suppose I have a sparse enumeration type: > > type Enum is (Ten, Twenty, Thirty); > for Enum use (10, 20, 30); > for Enum'Size use 8; > >and a corresponding integer type: > > type Int_Type is range 0 .. 31; > for Int_Type'Size use 8; > >Given an arbitrary value of type Int_Type, is there any non-erroneous >way to get the corresponding Enum value if there is one, or raise >an exception if there isn't? By "corresponding", I mean 10 => Ten, >20 => Twenty, 30 => Thirty. Creating a lookup table that duplicates >the information in the enumeration representation clause doesn't count; >consider that Enum might be a generic formal type. The 'Val attribute >won't work, since it uses the position number (0, 1, 2) rather than the >internal representation (10, 20, 30). The answer would appear to be, No, there is no way to automatically get Ada to raise an exception. You have to check for a correct value before unchecked converting to type Enum: function To_Enum is new Unchecked_Conversion (Int_Type, Enum); I : Int_Type := ...; E : Enum; begin case I is when 10 | 20 | 30 => E := To_Enum (I); when others => raise ; end case; end; You raise an interesting point, though: this solution is complicated by the fact that the representation values of type Enum are sparse. Had they been contiguous, you could force Ada to raise Constraint_Error via type qualification: type ET is (E1, E2, E3); for ET use (3, 4, 5); for ET'Size use 8; type IT is range 0 .. 31; for IT'Size use 8; function To_ET is new Unchecked_Conversion (IT, ET); subtype ET_Rep is IT range 3 .. 5; I : IT := ...; E : ET; begin E := To_ET (ET_Rep'(I)); -- will raise Constraint_Error if I not in 3 .. 5, -- thus preventing erroneous execution Of course, you could always instantiate Unchecked_Conversion using the subtype ET_Rep directly. Type qualification is useful technique for doing a kind of assertion checking, forcing Ada to raise Constraint_Error when a value doesn't satisfy a range constraint "precondition." It's much hipper than the explicit tests you see all the time: if I not in ET_Rep then -- why bother? raise ; end if; Type qualification gives you this for free. For a static subtype, qualification means you don't have to include all the branches in a case statement: case ET_Rep'(I) is -- will raise Constraint_Error if I not in 3 .. 5 when ET_Rep => -- other values for I don't have to be handled E := To_ET (I); end case; A similar technique is to use a subtype indication to enforce a precondition: I : IT range ET_Rep'Range := ...; After the expression on the right hand side is evaluated, Ada will check to make sure that it lies within the range of ET_Rep before making the assignment, raising Constraint_Error if the "precondition" isn't satisfied. A subtype indication is also a useful documentation tool: Max_Value : constant FT := ...; Value : constant FT := ...; Normalized_Value : constant FT range 0.0 .. 1.0 := Value / Max_Value; I'm giving the reader information, namely, that a "normalized value" means that it has the range 0.0 .. 1.0. I can use Ada to document this rather than resorting to a comment. -------------------------------------------------------------------- Matthew Heaney Software Development Consultant mheaney@ni.net (818) 985-1271