CS141 Lecture 17

Variant Records

What are Variant Records?

Variant RECORD TYPEs are RECORD TYPEs that support multiple record structures within a single record type.

Example: A geometric object record that has different components depending on whether the object is a rectangle (height and width) versus a circle (radius).

Picture:

Variant Record Structure

Note: The size of the record can change between variants!

How much memory should the compiler allocate for a variant record:
Answer: It depends!

When should you use Variant Records?

Answer: Rarely!

Most cases can be handled by Ada TAGGED TYPEs (same as classes and subclasses in C++ and Java) with less pain and a lot more flexibility. (In C and C++ Variant Records correspond to Unions. There is no corresponding capability in Java.)

Also, in Ada, you cannot use Variant Records to switch between different views of the same set of bits (a standard use for Unions in C and C++). In Ada use Unchecked_Conversion if you really(!) need to do this.

Historical Note: Variant RECORD TYPEs was an important feature of Ada83, which did not support TAGGED TYPEs. With the addition of TAGGED TYPEs in Ada95, Variant Records are mostly used in conjunction with old Ada code.

Defining a Variant Record

TYPE type_id( discriminant_id : discriminant_type := default_value )
  IS RECORD
   Id1 : Type1;
   ...
   fixed part of record
   ...
   Idn : Typen;

   CASE discriminant_id IS
      WHEN value1 =>
         fields for value1
      WHEN value2 =>
         fields for value2
      ...
      variant part
      ...
      WHEN valuen =>
         fields for valuen
      WHEN OTHERS =>
         fields for all other cases
   END CASE;
END RECORD;


Example:

TYPE Geom_Type IS (Unknown, Rectangle, Circle);
TYPE Geometric_Figure(Figure_Type : Geom_Type := Unknown) IS RECORD
   -- Invariant data fields here
   CASE Figure_Type IS
      WHEN Rectangle =>
         Width  : Float;
         Height : Float;
      WHEN Circle =>
         Radius : Float;
      WHEN Unknown =>
         NULL;
   END CASE;
END RECORD;


Notes:

Constrained and Unconstrained Variant Records

A Variant record object is Unconstrained if the variant can change (after the initial declaration). A Variant record object in Constrained if the variant can not be changed (after the initial declaration).

Memory allocation:
Example:

GF : Geometric_Figure;
   -- An unconstrained Geometric_Figure
GC : Geometric_Figure( Figure_Type => Circle );
   -- A constrained Geometric Figure of Figure_Type Circle


Note: An Unconstrained Variant Record object has its discriminant initialized to the default value specified in the declaration. Thus, if there is no default value for the discriminant, you cannot declare an unconstrained object.


Ada always guarantees:

Operations on Variant Records

  1. Retrieving field values:
  2. Storing field values:
  3. Record assignment:
  4. Record comparison:

Geometric Figures Example