4.6. Type Conversions

[PREVIOUS][UP][NEXT]

The evaluation of an explicit type conversion evaluates the expression given as the operand, and converts the resulting value to a specified target type. Explicit type conversions are allowed between closely related types as defined below.

    type_conversion ::= type_mark(expression)    

The target type of a type conversion is the base type of the type mark. The type of the operand of a type conversion must be determinable independently of the context (in particular, independently of the target type). Furthermore, the operand of a type conversion is not allowed to be a literal null, an allocator, an aggregate, or a string literal; an expression enclosed by parentheses is allowed as the operand of a type conversion only if the expression alone is allowed.

A conversion to a subtype consists of a conversion to the target type followed by a check that the result of the conversion belongs to the subtype. A conversion of an operand of a given type to the type itself is allowed.

The other allowed explicit type conversions correspond to the following three cases:

  1. Numeric types

    The operand can be of any numeric type; the value of the operand is converted to the target type which must also be a numeric type. For conversions involving real types, the result is within the accuracy of the specified subtype (see 4.5.7). The conversion of a real value to an integer type rounds to the nearest integer; if the operand is halfway between two integers (within the accuracy of the real subtype) rounding may be either up or down.

  2. Derived types

    The conversion is allowed if one of the target type and the operand type is derived from the other, directly or indirectly, or if there exists a third type from which both types are derived, directly or indirectly.

  3. Array types

    The conversion is allowed if the operand type and the target type are array types that satisfy the following conditions: both types must have the same dimensionality; for each index position the index types must either be the same or be convertible to each other; the component types must be the same; finally, if the component type is a type with discriminants or an access type, the component subtypes must be either both constrained or both unconstrained. If the type mark denotes an unconstrained array type, then, for each index position, the bounds of the result are obtained by converting the bounds of the operand to the corresponding index type of the target type. If the type mark denotes a constrained array subtype, then the bounds of the result are those imposed by the type mark. In either case, the value of each component of the result is that of the matching component of the operand (see 4.5.2).

In the case of conversions of numeric types and derived types, the exception CONSTRAINT_ERROR is raised by the evaluation of a type conversion if the result of the conversion fails to satisfy a constraint imposed by the type mark.

In the case of array types, a check is made that any constraint on the component subtype is the same for the operand array type as for the target array type. If the type mark denotes an unconstrained array type and if the operand is not a null array, then, for each index position, a check is made that the bounds of the result belong to the corresponding index subtype of the target type. If the type mark denotes a constrained array subtype, a check is made that for each component of the operand there is a matching component of the target subtype, and vice versa. The exception CONSTRAINT_ERROR is raised if any of these checks fails.

If a conversion is allowed from one type to another, the reverse conversion is also allowed. This reverse conversion is used where an actual parameter of mode in out or out has the form of a type conversion of a (variable) name as explained in section 6.4.1.

Apart from the explicit type conversions, the only allowed form of type conversion is the implicit conversion of a value of the type universal_integer or universal_real into another numeric type. An implicit conversion of an operand of type universal_integer to another integer type, or of an operand of type universal_real to another real type, can only be applied if the operand is either a numeric literal, a named number, or an attribute; such an operand is called a convertible universal operand in this section. An implicit conversion of a convertible universal operand is applied if and only if the innermost complete context (see 8.7) determines a unique (numeric) target type for the implicit conversion, and there is no legal interpretation of this context without this conversion.

Notes:

The rules for implicit conversions imply that no implicit conversion is ever applied to the operand of an explicit type conversion. Similarly, implicit conversions are not applied if both operands of a predefined relational operator are convertible universal operands.

The language allows implicit subtype conversions in the case of array types (see 5.2.1). An explicit type conversion can have the effect of a change of representation (in particular see 13.6). Explicit conversions are also used for actual parameters (see 6.4).

Examples of numeric type conversion:

    REAL(2*J)      --  value is converted to floating point
    INTEGER(1.6)   --  value is 2
    INTEGER(-0.4)  --  value is 0

Example of conversion between derived types:

    type A_FORM is new B_FORM; 

    X : A_FORM;
    Y : B_FORM; 

    X := A_FORM(Y);
    Y := B_FORM(X);  --  the reverse conversion 

Examples of conversions between array types:

    type SEQUENCE is array (INTEGER range <>) of INTEGER;
    subtype DOZEN is SEQUENCE(1 .. 12);
    LEDGER : array(1 .. 100) of INTEGER;

    SEQUENCE(LEDGER)            --  bounds are those of LEDGER
    SEQUENCE(LEDGER(31 .. 42))  --  bounds are 31 and 42
    DOZEN(LEDGER(31 .. 42))     --  bounds are those of DOZEN 

Examples of implicit conversions:

    X : INTEGER := 2; 

    X + 1 + 2              -- implicit conversion of each integer literal
    1 + 2 + X              -- implicit conversion of each integer literal
    X + (1 + 2)            -- implicit conversion of each integer literal 

    2 = (1 + 1)            -- no implicit conversion:  the type is uni-
                              versal_integer
    A'LENGTH = B'LENGTH    -- no implicit conversion:  the type is uni-
                              versal_integer
    C : constant := 3 + 2; -- no implicit conversion:  the type is uni-
                              versal_integer

    X = 3 and 1 = 2        -- implicit conversion of 3, but not of 1 and 2 

References: actual parameter, array type, attribute, base type, belong to a subtype, component, constrained array subtype, constraint_error exception, derived type, dimension, expression, floating point type, index, index subtype, index type, integer type, matching component, mode, name, named number, null array, numeric literal, numeric type, raising of exceptions, real type, representation, statement, subtype, type, type mark, unconstrained array type, universal_integer type, universal_real type, variable.


[INDEX][CONTENTS]