We end this chapter about abstract containers with a small detour, introducing
extensions to the tt(union) concept. Although unions themselves aren't
`abstract containers', having covered containers puts us in a good position
to introduce and illustrate
    hi(unrestricted union)em(unrestricted unions).

Whereas traditional unions can only contain primitive data, unrestricted
unions allow addition of data fields of types for which non-trivial
constructors have been defined. Such data fields commonly are of
class-types. Here is an example of such an unrestricted union:
        verb(
    union Union
    {
        int u_int;
        std::string u_string;
    };
        )
    One of its fields defines a constructor, turning this union into an
em(unrestricted) union.  As an unrestricted union defines at least one field
of a type having a constructor the question becomes how these unions can be
constructed and destroyed.

The destructor of a union consisting of, e.g. a tt(std::string) and an
tt(int) should of course not call the tt(string)'s destructor if the
union's last (or only) use referred to its tt(int) field. Likewise, when
the tt(std::string) field is used, and processing switches from the
tt(std::string) to the tt(int) field, tt(std::string)'s destructor
should be called before any assignment to the tt(int) field takes place.

The compiler does not solve the issue for us, and in fact does em(not)
implement default constructors or destructors for unrestricted unions at
all. If we try to define an unrestricted union like the one shown above, an
error message like the following is issued:
        verb(
    error: use of deleted function 'Union::Union()'
    error: 'Union::Union()' is implicitly deleted because the default
            definition would be ill-formed:
    error: union member 'Union::u_string' with non-trivial
            'std::basic_string<...>::basic_string() ...'
        )
