Generics in Ada

Like most other modern languages, Ada does have mechanisms for Generic programming. A solid introduction can be found in this AdaCore Article.

Types of generics in Ada

Ada basically supports two types of Generics. In Ada terminology, we speak about generic units. A unit is either a package or a single subprogram, so the following cases do exist but are d

  • Generic subprograms (single procedures or functions taking and/or returning generic parameters)

  • Package-level generics. Entire packages that operate on generic parameters.

Subprogram-level Generics

A generic subprogram is a function or a procedure that takes one or more formal type parameters. A function may also return a formal type value. Like any other Ada unit, it is specified in an .ads file and implemented in an .adb file. Such subprograms are not part of a package and thus are part of the global name space. Naming conventions dictate that the name of the subprogram is also the file name. Since our example procedure is named Swap we must also name the files swap.[adb|ads] [1].

A generic procedure - spec file
1-- specs in the swap.ads
2generic
3  type Element_T is private;  -- generic type parameter (placeholder)
4-- a procedure using such a type.
5procedure Swap (X, Y : in out Element_T);
A generic procedure - body implementation
1-- implementation in swap.adb
2procedure Swap (X, Y : in out Element_T) is
3  Temporary : constant Element_T := X;
4begin
5  X := Y;
6  Y := Temporary;
7end Swap;

To instantiate this generic procedure we would use it like procedure Swap_Integers is new Swap (Integer);. after making the generic procedure availble with a With Swap; statement. Afterwards, you can use the procedure like so: Swap_Integers(foo, bar) (given that foo and bar are two Integer variables).

Note

For more clarity (and verbosity 😄), we could also use named parameter notation and write (Element_T => Integer);, but this is often omitted, particularly when there is only one formal type parameter.

Hint

In C++, Java and other languages with heavy generics content, it is often idiomatic to name type parameters with a single capital letter like T, V or W. In Ada, which is case-insensitive, more descriptive names, often with Element_ as a prefix are common.

The formal type parameter is declared in line 3 as a private type.

Package-level generics

This is the much more common variant of using generics in Ada. Formal type parameters apply to an entire package and can be used in all subprograms and other declarations throughout this package.

Package spec
1generic
2  Max: Positive;
3  type Element_T is private;
4package Generic_Stack is
5  procedure Push (E: Element_T);
6  function Pop return Element_T;
7end Generic_Stack;
Package implementation
1package body Generic_Stack is
2Stack: array (1 .. Max) of Element_T;
3Top  : Integer range 0 .. Max := 0;  -- initialise to empty
4-- ...
5end Generic_Stack;

Generic packages must be instantiated before you can make such a package available with a With Statement. To do so you simple define a new package package Float_Stack is new Generic_Stack(Float);

Differences to C++ or Java

In C++ or Java (and other languages) you instantiate a generic class or method by using it. In Ada, you need to instantiate either a generic subprogram or a generic class, essentially creating a usable version of the subprogram or the package.

Tags: ada