# Ada Programming/Generics


## Parametric polymorphism (generic units)

The idea of code reuse arises from the necessity for constructing large
software systems combining well-established building blocks. The
reusability of code improves the productivity and the quality of
software. The generic units are one of the ways in which the Ada
language supports this characteristic. A generic unit is a subprogram or
package that defines algorithms in terms of types and operations that
are not defined until the user instantiates them.

Note to C++ programmers: generic units are similar to C++ templates.

For example, to define a procedure for swapping variables of any
(non-limited) type:

\
`  `` Element_T `` ``;  `\
` Swap (X, Y : `` `` Element_T);`

` Swap (X, Y : `` `` Element_T) `\
`  Temporary : `` Element_T := X;`\
\
`  X := Y;`\
`  Y := Temporary;`\
` Swap;`

The `Swap` subprogram is said to be generic. The subprogram
specification is preceded by the generic formal part consisting of the
reserved word  followed by a list of
generic formal parameters which may be empty. The entities declared as
generic are not directly usable, it is necessary to instantiate them.

To be able to use `Swap`, it is necessary to create an instance for the
wanted type. For example:

` Swap_Integers `` `` Swap (Integer);`

Now the `Swap_Integers` procedure can be used for variables of type
`Integer`.

The generic procedure can be instantiated for all the needed types. It
can be instantiated with different names or, if the same identifier is
used in the instantiation, each declaration overloads the procedure:

` Instance_Swap `` `` Swap (Float);`\
` Instance_Swap `` `` Swap (Day_T);`\
` Instance_Swap `` `` Swap (Element_T => Stack_T);`

Similarly, generic packages can be used, for example, to implement a
stack of any kind of elements:

\
`  Max: Positive; `\
`  `` Element_T `` ``;`\
` Generic_Stack `\
`  `` Push (E: Element_T);`\
`  `` Pop return Element_T;`\
` Generic_Stack;`

` `` Generic_Stack `\
`  Stack: `` (1 .. Max) `` Element_T;`\
`  Top  : Integer `` 0 .. Max := 0;  `\
`  `\
` Generic_Stack;`

A stack of a given size and type could be defined in this way:

\
`  `` Float_100_Stack `` `` Generic_Stack (100, Float);`\
`  `` Float_100_Stack;`\
\
`  Push (45.8);`\
`  `\
`;`

## Generic parameters

The generic unit declares *generic formal parameters*, which can be:

-   objects (of mode *in* or *in out* but never *out*)
-   types
-   subprograms
-   instances of another, designated, generic unit.

When instantiating the generic, the programmer passes one *actual
parameter* for each formal. Formal values and subprograms can have
defaults, so passing an actual for them is optional.

### Generic formal objects

Formal parameters of mode *in* accept any value, constant, or variable
of the designated type. The actual is copied into the generic instance,
and behaves as a constant inside the generic; this implies that the
designated type cannot be limited. It is possible to specify a default
value, like this:

\
`   Object : `` Natural := 0;`

For mode *in out*, the actual must be a variable.

One limitation with generic formal objects is that they are never
considered static, even if the actual happens to be static. If the
object is a number, it cannot be used to create a new type. It can
however be used to create a new derived type, or a subtype:

\
`   Size : `` Natural := 0;`\
` P `\
`   `` T1 `` `` Size; `\
`   `` T2 `` `` 1 .. Size; `\
`   `` T3 `` `` Integer `` 1 .. Size; `\
`   `` T4 `` Integer `` 1 .. Size; `\
` P;`

The reason why formal objects are nonstatic is to allow the compiler to
emit the object code for the generic only once, and to have all
instances share it, passing it the address of their actual object as a
parameter. This bit of compiler technology is called *shared generics*.
If formal objects were static, the compiler would have to emit one copy
of the object code, with the object embedded in it, for each instance,
potentially leading to an explosion in object code size (*code bloat*).

(Note to C++ programmers: in C++, since formal objects can be static,
the compiler cannot implement shared generics in the general case; it
would have to examine the entire body of the generic before deciding
whether or not to share its object code. In contrast, Ada generics are
designed so that the compiler can instantiate a generic *without looking
at its body*.)

### Generic formal types

The syntax allows the programmer to specify which type categories are
acceptable as actuals. As a rule of thumb: The syntax expresses how the
generic sees the type, i.e. it assumes the worst, not how the creator of
the instance sees the type.

This is the syntax of RM :

` formal_type_declaration ::=`\
`   `` defining_identifier[discriminant_part] `` formal_type_definition;`\
` `\
` formal_type_definition ::= formal_private_type_definition`\
`                          | formal_derived_type_definition`\
`                          | formal_discrete_type_definition`\
`                          | formal_signed_integer_type_definition`\
`                          | formal_modular_type_definition`\
`                          | formal_floating_point_definition`\
`                          | formal_ordinary_fixed_point_definition`\
`                          | formal_decimal_fixed_point_definition`\
`                          | formal_array_type_definition`\
`                          | formal_access_type_definition`\
`                          | formal_interface_type_definition`

This is quite complex, so some examples are given below. A type declared
with the syntax ` T (<>)` denotes a type
with *unknown discriminants*. This is the Ada vernacular for indefinite
types, i.e. types for which objects cannot be declared without giving an
initial expression. An example of such a type is one with a discriminant
without default, another example is an unconstrained array type.

  Generic formal type                                                                                                                                                                                                  Acceptable actual types
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  ` T (<>) `` `` ``;`                                                                          Any type at all. The actual type can be limited or not, indefinite or definite, but the *generic* treats it as limited and indefinite, i.e. does not assume that assignment is available for the type.
  ` T (<>) `` ``;`                                                                                                             Any nonlimited type: the generic knows that it is possible to assign to variables of this type, but it is not possible to declare objects of this type without initial value.
  ` T `` ``;`                                                                                                                  Any nonlimited definite type: the generic knows that it is possible to assign to variables of this type and to declare objects without initial value.
  ` T (<>) `` `` `` `` ``;`    Any tagged type, abstract or concrete, limited or not.
  ` T (<>) `` `` `` ``;`                                        Any concrete tagged type, limited or not.
  ` T (<>) `` `` `` ``;`                                       Any nonlimited tagged type, abstract or concrete.
  ` T (<>) `` `` ``;`                                                                           Any nonlimited, concrete tagged type.
  ` T (<>) `` `` Parent;`                                                                                                          Any type derived from `Parent`. The generic knows about `Parent`\'s operations, so can call them. Neither `T` nor `Parent` can be abstract.
  ` T (<>) `` `` `` Parent `` ``;`   Any type, abstract or concrete, derived from `Parent`, where `Parent` is a tagged type, so calls to `T`\'s operations can dispatch dynamically.
  ` T (<>) `` `` Parent `` ``;`                                       Any concrete type, derived from the tagged type `Parent`.
  ` T `` (<>);`                                                                                                                                                Any discrete type: integer, modular, or enumeration.
  ` T `` `` <>;`                                                                                                                 Any signed integer type
  ` T `` `` <>;`                                                                                                                   Any modular type
  ` T `` `` <>;`                                                                                                                 Any (non-decimal) fixed point type
  ` T `` `` <> `` <>;`                                                                            Any decimal fixed point type
  ` T `` `` <>;`                                                                                                                Any floating point type
  `<code>`{=html} T   (I)  E;                                                                         Any array type with index of type `I` and elements of type `E` (`I` and `E` could be formal parameters as well)
  ` T `` `` O;`                                                                                                                 Any access type pointing to objects of type `O` (`O` could be a formal parameter as well)

In the body we can only use the operations predefined for the type
category of the formal parameter. That is, the generic specification is
a contract between the generic implementor and the client instantiating
the generic unit. This is different to the parametric features of other
languages, such as C++.

It is possible to further restrict the set of acceptable actual types
like so:

  Generic formal type                                                          Acceptable actual types
  ---------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------
  ` T (<>) `\...       Definite or indefinite types (loosely speaking: types with or without discriminants, but other forms of indefiniteness exist)
  ` T (D : DT) `\...   Types with a discriminant of type DT (it is possible to specify several discriminants, too)
  ` T `\...            Definite types (loosely speaking types without a discriminant or with a discriminant with default value)

### Generic formal subprograms

It is possible to pass a subprogram as a parameter to a generic. The
generic specifies a generic formal subprogram, complete with parameter
list and return type (if the subprogram is a function). The actual must
match this parameter profile. It is not necessary that the *names* of
parameters match, though.

Here is the specification of a generic subprogram that takes another
subprogram as its parameter:

\
`  `` Element_T `` ``;`\
`  `` `` "*" (X, Y: Element_T) `` Element_T;`\
` Square (X : Element_T) `` Element_T;`

And here is the body of the generic subprogram; it calls parameter as it
would any other subprogram.

` Square (X: Element_T) `` Element_T `\
\
`  `` X * X;   `\
` Square;`

This generic function could be used, for example, with matrices, having
defined the matrix product.

` Square;`\
` Matrices;`\
` Matrix_Example `\
`  `` Square_Matrix `` `` Square`\
`    (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);`\
`  A : Matrices.Matrix_T := Matrices.Identity;`\
\
`  A := Square_Matrix (A);`\
` Matrix_Example;`

It is possible to specify a default with \"the box\"
(` `), like
this:

\
`  `` Element_T `` ``;`\
`  `` `` "*" (X, Y: Element_T) `` Element_T `` <>;`

This means that if, at the point of instantiation, a function \"\*\"
exists for the actual type, and if it is directly visible, then it will
be used by default as the actual subprogram.

One of the main uses is passing needed operators. The following example
shows this `<small>`{=html}(follow download links for full
example)`</small>`{=html}:

`  `

`  `\
`     `` Element_Type `` ``;`\
`     `*`...`*\
`     `` `` "<"`\
`       (Left  : `` Element_Type;`\
`        Right : `` Element_Type)`\
`        ``  Boolean`\
`     `` ``;`\
`  `` Search`\
`    (Elements : `` Array_Type;`\
`     Search   : `` Element_Type;`\
`     Found    : `` Boolean;`\
`     Index    : `` Index_Type'``)`\
`     `*`...`*

### Generic instances of other generic packages

A generic formal can be a package; it must be an instance of a generic
package, so that the generic knows the interface exported by the
package:

\
`   `` `` P `` `` Q (``);`

This means that the actual must be an instance of the generic package Q.
The box after Q means that we do not care which actual generic
parameters were used to create the actual for P. It is possible to
specify the exact parameters, or to specify that the defaults must be
used, like this:

\
`   `\
`   `` `` P1 `` `` Q (Param1 => X, Param2 => Y);`\
\
`   `\
`   `` `` P2 `` `` Q;`\

You can specify one default parameters, none or only some. Defaults are
indicated with a box (\" =\> \<\> \"), and you can use \" others =\>
\<\>\") to mean \"use defaults for all parameters not mentioned\". The
actual package must, of course, match these constraints.

The generic sees both the public part and the generic parameters of the
actual package (Param1 and Param2 in the above example).

This feature allows the programmer to pass arbitrarily complex types as
parameters to a generic unit, while retaining complete type safety and
encapsulation. *(example needed)*

It is not possible for a package to list itself as a generic formal, so
no generic recursion is possible. The following is illegal:

` A;`\
\
`   `` `` P `` `` A (``);`\
` A; `

In fact, this is only a particular case of:

` A; `\
` A;`

which is also illegal, despite the fact that A is no longer generic.

## Instantiating generics

To instantiate a generic unit, use the keyword **new**:

` Square_Matrix `` `` Square`\
`   (Element_T => Matrices.Matrix_T, "*" => Matrices.Product);`

Notes of special interest to C++ programmers:

-   The generic formal types define *completely* which types are
    acceptable as actuals; therefore, the compiler can instantiate
    generics without looking at the body of the generic.
-   Each instance has a name and is different from all other instances.
    In particular, if a generic package declares a type, and you create
    two instances of the package, then you will get two different,
    incompatible types, even if the actual parameters are the same.
-   Ada requires that all instantiations be explicit.
-   It is not possible to create special-case instances of a generic
    (known as \"template specialisation\" in C++).

As a consequence of the above, Ada does not permit template
metaprogramming. However, this design has significant advantages:

-   the object code can be shared by all instances of a generic, unless
    of course the programmer has requested that subprograms be inlined;
    there is no danger of code bloat.
-   when reading programs written by other people, there are no hidden
    instantiations, and no special cases to worry about. Ada follows the
    Law of Least Astonishment.

## Advanced generics

### Generics and nesting

A generic unit can be nested inside another unit, which itself may be
generic. Even though no special rules apply (just the normal rules about
generics and the rules about nested units), novices may be confused. It
is important to understand the difference between a generic unit and
*instances* of a generic unit.

**Example 1**. A generic subprogram nested in a nongeneric package.

` Bag_Of_Strings `\
`   `` Bag `` ``;`\
`   `\
`      `` `` Operator (S : `` `` String);`\
`   `` Apply_To_All (B : `` `` Bag);`\
\
`   `\
` Bag_Of_Strings;`

To use **Apply_To_All**, you first define the procedure to be applied to
each String in the Bag. Then, you instantiate **Apply_To_All**, and
finally you call the instance.

` Bag_Of_Strings;`\
` Example_1 `\
`   `` Capitalize (S : `` `` String) `` ``; `\
`   `` Capitalize_All `\
`      `` Bag_Of_Strings.Apply_To_All (Operator => Capitalize);`\
`   B : Bag_Of_Strings.Bag;`\
\
`   Capitalize_All (B);`\
` Example_1;`

**Example 2.** A generic subprogram nested in a generic package

This is the same as above, except that now the Bag itself is generic:

\
`   `` Element_Type (<>) `` ``;`\
` Generic_Bag `\
`   `` Bag `` ``;`\
`   `\
`      `` `` Operator (S : `` `` Element_Type);`\
`   `` Apply_To_All (B : `` `` Bag);`\
\
`   `\
` Generic_Bag;`

As you can see, the generic formal subprogram **Operator** takes a
parameter of the generic formal type **Element_Type**. This is okay: the
nested generic sees everything that is in its enclosing unit.

You cannot instantiate **Generic_Bag.Apply_To_All** directly, so you
must first create an instance of **Generic_Bag**, say
**Bag_Of_Strings**, and then instantiate
**Bag_Of_Strings.Apply_To_All**.

` Generic_Bag;`\
` Example_2 `\
`   `` Capitalize (S : `` `` String) `` ``; `\
`   `` Bag_Of_Strings `\
`      `` Generic_Bag (Element_Type => String);`\
`   `` Capitalize_All `\
`      `` Bag_Of_Strings.Apply_To_All (Operator => Capitalize);`\
`   B : Bag_Of_Strings.Bag;`\
\
`   Capitalize_All (B);`\
` Example_2;`

### Generics and child units

**Example 3**. A generic unit that is a child of a nongeneric unit.

Each instance of the generic child is a child of the parent unit, and so
it can see the parent\'s public and private parts.

` Bag_Of_Strings `\
`   `` Bag `` ``;`\
\
`   `\
` Bag_Of_Strings; `\
\
\
`   `` `` Operator (S : `` `` String);`\
` Bag_Of_Strings.Apply_To_All (B : `` `` Bag);`

The differences between this and Example 1 are:

-   **Bag_Of_Strings.Apply_To_All** is compiled separately. In
    particular, **Bag_Of_Strings.Apply_To_All** might have been written
    by a different person who did not have access to the source text of
    **Bag_Of_Strings**.
-   Before you can use **Bag_Of_Strings.Apply_To_All**, you must
    **with** it explicitly; **with**ing the parent, **Bag_Of_Strings**,
    is not sufficient.
-   If you do not use **Bag_Of_Strings.Apply_To_All**, your program does
    not contain its object code.
-   Because **Bag_Of_Strings.Apply_To_All** is at the library level, it
    can declare controlled types; the nested package could not do that
    in Ada 95. In Ada 2005, one can declare controlled types at any
    level.

` Bag_Of_Strings.Apply_To_All; `\
` Example_3 `\
`   `` Capitalize (S : `` `` String) `` ``; `\
`   `` Capitalize_All `\
`      `` Bag_Of_Strings.Apply_To_All (Operator => Capitalize);`\
`   B : Bag_Of_Strings.Bag;`\
\
`   Capitalize_All (B);`\
` Example_3;`

**Example 4**. A generic unit that is a child of a generic unit

This is the same as Example 3, except that now the Bag is generic, too.

\
`   `` Element_Type (<>) `` ``;`\
` Generic_Bag `\
`   `` Bag `` ``;`\
\
`   `\
` Generic_Bag;`\
\
\
`   `` `` Operator (S : `` `` Element_Type);`\
` Generic_Bag.Apply_To_All (B : `` `` Bag);`\
\
` Generic_Bag.Apply_To_All;`\
` Example_4 `\
`   `` Capitalize (S : `` `` String) `` ``; `\
`   `` Bag_Of_Strings `\
`      `` Generic_Bag (Element_Type => String);`\
`   `` Capitalize_All `\
`      `` Bag_Of_Strings.Apply_To_All (Operator => Capitalize);`\
`   B : Bag_Of_Strings.Bag;`\
\
`   Capitalize_All (B);`\
` Example_4;`

**Example 5**. A parameterless generic child unit

Children of a generic unit **must** be generic, no matter what. If you
think about it, it is quite logical: a child unit sees the public and
private parts of its parent, including the variables declared in the
parent. If the parent is generic, which instance should the child see?
The answer is that the child must be the child of only one instance of
the parent, therefore the child must also be generic.

\
`   `` Element_Type (<>) `` ``;`\
`   `` Hash_Type `` (<>);`\
`   `` `` Hash_Function (E : Element_Type) `` Hash_Type;`\
` Generic_Hash_Map `\
`   `` Map `` ``;`\
\
`   `\
` Generic_Hash_Map;`

Suppose we want a child of a **Generic_Hash_Map** that can serialise the
map to disk; for this it needs to sort the map by hash value. This is
easy to do, because we know that **Hash_Type** is a discrete type, and
so has a less-than operator. The child unit that does the serialisation
does not need any additional generic parameters, but it must be generic
nevertheless, so it can see its parent\'s generic parameters, public and
private part.

\
` Generic_Hash_Map.Serializer `\
`    `` Dump (Item : `` Map; To_File : `` String);`\
`    `` Restore (Item : `` Map; From_File : `` String);`\
` Generic_Hash_Map.Serializer;`\

To read and write a map to disk, you first create an instance of
**Generic_Hash_Map**, for example **Map_Of_Unbounded_Strings**, and then
an instance of **Map_Of_Unbounded_Strings.Serializer**:

` Ada.Strings.Unbounded;`\
` Generic_Hash_Map.Serializer;`\
` Example_5 `\
`   `` Ada.Strings.Unbounded;`\
`   `` Hash (S : `` Unbounded_String) `` Integer `` ``; `\
`   `` Map_Of_Unbounded_Strings `\
`      `` Generic_Hash_Map (Element_Type => Unbounded_String,`\
`                            Hash_Type => Integer,`\
`                            Hash_Function => Hash);`\
`   `` Serializer `\
`      `` Map_Of_Unbounded_Strings.Serializer;`\
`   M : Map_Of_Unbounded_Strings.Map;`\
\
`   Serializer.Restore (Item => M, From_File => "map.dat");`\
` Example_5;`

## See also

### Wikibook

-   Ada Programming
-   Ada Programming/Object
    Orientation: tagged
    types provides other mean of polymorphism in Ada.

### Wikipedia

-   Generic programming

### Ada Reference Manual

-   
Programming}}\|Generics

es:Programación en Ada/Unidades
genéricas
