1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
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 were 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 is defined as a tt(std::string) (having 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 not at all
implement default constructors or destructors for unrestricted unions. If we
try to define an unrestricted union like the one shown above, an error message
is issued. E.g.,
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() ...')
|