Ada-Rapporteur-Group / User-Community-Input

Ada User Community Input Working Group - Github Mirror Prototype
26 stars 1 forks source link

'Valid for numeric types (with Universal_Real and Universal_Integer parameter) #96

Open joshua-c-fletcher opened 3 months ago

joshua-c-fletcher commented 3 months ago

I named the title for Issue #95 ('Valid for enumerations), since this is a similar proposal in concept.

That one was "To be able to know in advance if a 'Value is going to succeed or raise." This one is about knowing if a cast will succeed or raise.

Suppose you have a value of a numeric type, and you want to assign it to a variable of a different numeric type that has (or may have) a different range. If you want to be sure the cast will work, you need to ensure it is within the range of the target type before you cast.

In the most general case, you need to pick a type that will support the range of the target type and the value you want to assign to it (perhaps using one of the type 'Base type, which would be less constrained, or using a type like [[Long]Long]Float or [[Long]Long]Integer).. then you can check if the value is in range like this:

if Broad_Type(Value) in Broad_Type(Target_Type'First) .. Broad_Type(Target_Type'Last) then Target := Value; end if;

when Broad_Type might be Target_Type'Base, you could do: if Target_Type'Base (Value) in Target_Type'Range then

... but the rules for 'Base don't ensure that the latter approach would always work (you could get a constraint_error on the Target_Type'Base cast, because the range of a 'Base type isn't universal.)

'In_Range (Universal_Real) 'In_Range (Universal_Integer) for numeric types might be a better name than 'Valid

if Target_Type'In_Range (Value) then Target := Target_Type (Value); end if;

Note: this attribute could also consider values that would be omitted by a predicate, when applicable.