Ada 95 Quality and Style Guide Chapter 8

Chapter 8: Reusability - TOC - 8.2 ROBUSTNESS

8.2.4 Subtypes in Generic Specifications


  • Use first subtypes when declaring generic formal objects of mode in out.
  • Beware of using subtypes as subtype marks when declaring parameters or return values of generic formal subprograms.
  • Use attributes rather than literal values.

  • example

    In the following example, it appears that any value supplied for the generic formal object Object would be constrained to the range 1..10. It also appears that parameters passed at run-time to the Put routine in any instantiation and values returned by the Get routine would be similarly constrained:

       subtype Range_1_10 is Integer range 1 .. 10;
          Object : in out Range_1_10;
          with procedure Put (Parameter : in     Range_1_10);
          with function  Get return Range_1_10;
       package Input_Output is
       end Input_Output;

    However, this is not the case. Given the following legal instantiation:

       subtype Range_15_30 is Integer range 15 .. 30;
       Constrained_Object : Range_15_30 := 15;
       procedure Constrained_Put (Parameter : in     Range_15_30);
       function  Constrained_Get return Range_15_30;
       package Constrained_Input_Output is
          new Input_Output (Object => Constrained_Object,
                            Put    => Constrained_Put,
                            Get    => Constrained_Get);

    Object, Parameter, and the return value of Get are constrained to the range 15..30. Thus, for example, if the body of the generic package contains an assignment statement:

    Object := 1;

    Constraint_Error is raised when this instantiation is executed.


    The language specifies that when constraint checking is performed for generic formal objects and parameters and return values of generic formal subprograms, the constraints of the actual subtype (not the formal subtype) are enforced (Ada Reference Manual 1995, §§12.4"> and 12.6).Thus, the subtype specified in a formal in out object parameter and the subtypes specified in the profile of a formal subprogram need not match those of the actual object or subprogram.

    Thus, even with a generic unit that has been instantiated and tested many times and with an instantiation that reported no errors at instantiation time, there can be a run-time error. Because the subtype constraints of the generic formal are ignored, the Ada Reference Manual (1995, §§12.4 and 12.6) suggests using the name of a base type in such places to avoid confusion. Even so, you must be careful not to assume the freedom to use any value of the base type because the instantiation imposes the subtype constraints of the generic actual parameter. To be safe, always refer to specific values of the type via symbolic expressions containing attributes like 'First, 'Last, 'Pred, and 'Succ rather than via literal values.

    For generics, attributes provide the means to maintain generality. It is possible to use literal values, but literals run the risk of violating some constraint. For example, assuming that an array's index starts at 1 may cause a problem when the generic is instantiated for a zero-based array type.


    Adding a generic formal parameter that defines the subtype of the generic formal object does not address the ramifications of the constraint checking rule discussed in the above rationale. You can instantiate the generic formal type with any allowable subtype, and you are not guaranteed that this subtype is the first subtype:

       type Object_Range is range <>;
       Objects : in out Object_Range;
    package X is
    end X;

    You can instantiate the subtype Object_Range with any Integer subtype, for example, Positive. However, the actual variable Object can be of Positive'Base, i.e., Integer and its value are not guaranteed to be greater than 0.

    < Previous Page Search Contents Index Next Page >
    1 2 3 4 5 6 7 8 9 10 11
    Appendix References Bibliography