Channels ▼
RSS

C/C++

Discriminated Unions


Using the shape_area function dramatically simplifies the largest function, as shown in Listing Two.

Listing Two: A function that finds the largest shape in an array of shapes, using the shape_area function.

shape const *largest(shape const s[], size_t n) {
    shape const *p = NULL;
    double max = -1;
    size_t i;
    for (i = 0; i < n; ++i) {
        double area = shape_area(&s[i]);
        if (area > max) {
            max = area;
            p = &s[i];
        }
    }
    return p;
}

Correctness and Maintenance Problems

One of the problems with discriminated unions is that they require a lot of discipline to ensure that you don't access a union member unless it's the currently active member as indicated by the discriminator. In most cases, this means you should be scrupulous about wrapping the accesses to union members inside if- or switch-statements that test the discriminator.

Unfortunately, nothing in C prevents accidents such as:

case sk_rectangle:
    area = s->u.triangle.side1
        * s->u.triangle.side2;
    ~~~

This code will compile and then produce unpredictable, possibly erroneous, run-time results.

Some languages, such as Ada, have built-in support for discriminated unions intended to prevent such mishaps. Andrei Alexandescru showed how you can implement safe discriminated unions in C++ using template metaprogramming techniques (see his Generic <Programming> columns Discriminated Unions (I) and Discriminated Unions (II)).

Another problem with discriminated unions is that they can easily lead to code that's hard to maintain. For example, in addition to the shape_area function, your application might include other shape operations such as shape_perimeter, shape_resize, or shape_put. Each function has a similar, if not identical, switch-statement structure as shape_area. If you add a new shape, or modify the attributes of an existing shape, you probably need to change every one of those functions.

Anonymous Unions

By the way, C++ and more recent dialects of C support anonymous unions. That is, you can leave the union itself unnamed and access the union members as if they were members of the enclosing structure. If you define the shape structure as:

struct shape {
    ~~~
    union {
        circle_part circle;
        rectangle_part rectangle;
        triangle_part triangle;
    };  // union name omitted
};

then you can simplify expressions such as:

s->u.rectangle.height = h;

to just:

s->rectangle.height = h;

My examples don’t use anonymous unions because I tested this code with older C compilers that don’t support them.

Virtual functions provide an alternative to discriminated unions that are safe, efficient, and often more maintainable. I'll discuss virtual functions in this context in future articles.


Dan Saks is president of Saks & Associates, a C/C++ training and consulting company. This article is adapted from an article that appeared earlier this year in EE Times.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video