In the literature a variant is also referred to as a tagged union or discriminated union. See for example the wikipedia article on a Tagged union [].
A C++ programmer can think of a variant as combining the features of an enum and a union. The Xc++ language provides special support for defining variant data types.
A (closed) variant is a value-type that can represent exactly one value from a specified set of value-types. A closed variant definition is very similar to a tuple definition except that instead of defining a set of attribute-type + attribute-name pairs, it defines a set of tag-type + tag-name pairs. Furthermore unlike a tuple definition a tag-type is optional.
For example
$variant+ Shape
{
Circle circle;
Triangle triangle;
Rectangle rectangle;
};
A value of type Shape can represent either a circle, triangle or rectangle value. The identifiers ‘circle’, ‘triangle’ and ‘rectangle’ are tag-names and any valid C/C++ identifier may be used. The types of the tag-names (Circle, Triangle and Rectangle) are called tag-types.
The tag-type declaration that precedes a given tag-name is optional. For example, the following example is equivalent to a simple enumerated type in C/C++. There is no additional state associated with any of the tags.
$variant+ PrimaryColour
{
red;
green;
blue;
};
It is straightforward to map a variant into an efficient grammar for a binary encoding. Serialisation of a variant involves writing the tag (eg using an int32) then the additional state for that tag if any. Note that the serialisation is very efficient.
Schema evolution is supported in a similar fashion to tuples. Conceptually new tags may only be added to the end, and dropped tags are only marked as dropped. [todo: arguably tags can never be dropped]
Anonymous tuple definitions are often useful within variant definitions. For example, Shape could instead be written as follows
$variant+ Shape
{
tuple { Point centre; float32 radius; } circle;
tuple { Point[3] vertices; } triangle;
tuple Rectangle { float32 x1,y1,x2,y2; } rectangle;
};
When a $variant is reflected an instance of a ReflectedVariant is registered in the ReflectedVariant registry.