One of the features of C++ is the ability to declare a union, without specifying a name. Here’s an example:
union {
int a;
char b;
};
(yes, they can be useful, and I’ll give an example shortly). The standard [class.union.anon / 12.3.1] states the following limitations:
- Names of members of the anonymous union need to be distinct from any other in the scope of the declared union.
- Each variable declared in the union will have the same address (C++14)
- Anonymous unions can’t contain member functions
- all members are public
The main effect is that the members of a union are defined in scope after the anonymous union is defined. The members may be referenced as though they were any other variable in scope. For example:
int c;
union {
int a;
char b;
};
a = 1;
c = 2;
Where it is useful
Tagged unions are an interesting use-case:
Class Tagged{
union {
int a;
char b;
};
enum { INT_USED = 1, CHAR_USED=2 } tag;
};
Since like named unions, anonymous ones can only use one type at a time, the addition of the tag makes it safer if we want to change which member we use. However care must be taken to ensure we set both the member AND the tag. Using the class Tagged from above:
Tagged node;
// Some code...
// set the node
node.a = 12;
node.tag = INT_USED;
// Some more code..
node.b = 'Z';
node.tag = CHAR_USED;
Use case:
An interesting use case is binary tree construction. We can construct a tree based on a list of nodes, where each node contains a value, but its type can be either leaf or an internal node.
Another use case would be for a Shape class, where the coordinates of the different types of Shape are common, but the calculations for the area would be different for say a circle vs a square. The area function returns the appropriate value based on the tag value.
Library availability:
Finally, the Boost library went a little bit further and implemented a variant class template, boost::variant<> which provides the safety to use the different members without worry. It can also be quite useful when combined with boost::static_visitor<>.