[class.union.general]

# 11 Classes [[class]](./#class)

## 11.5 Unions [[class.union]](class.union#general)

### 11.5.1 General [class.union.general]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3186)

A [*union*](#def:union "11.5.1 General [class.union.general]") is a class defined with the [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]")union[.](#1.sentence-1)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3190)

In a union,
a non-static data member is [*active*](#def:active,union_member "11.5.1 General [class.union.general]") if its name refers to an object
whose lifetime has begun and has not ended ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#2.sentence-1)

At most one of the non-static data members of an object of union type
can be active at any
time, that is, the value of at most one of the non-static data members can be
stored in a union at any time[.](#2.sentence-2)

[*Note [1](#note-1)*:

One special guarantee is made in order to
simplify the use of unions: If a standard-layout union contains several standard-layout
structs that share a common initial sequence ([[class.mem]](class.mem "11.4 Class members")), and
if a non-static data member of an object of this standard-layout union type
is active and is one of the standard-layout structs,
the common initial sequence of any of the standard-layout struct members can be inspected;
see [[class.mem]](class.mem "11.4 Class members")[.](#2.sentence-3)

â *end note*]

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3209)

The size of a union is sufficient to contain the largest
of its non-static data members[.](#3.sentence-1)

Each non-static data member is allocated
as if it were the sole member of a non-union class[.](#3.sentence-2)

[*Note [2](#note-2)*:

A union object and its non-static data members are
pointer-interconvertible ([[basic.compound]](basic.compound "6.9.4 Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"))[.](#3.sentence-3)

As a consequence, all non-static data members of a
union object have the same address[.](#3.sentence-4)

â *end note*]

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3220)

A union can have member functions (including constructors and destructors),but it shall not have virtual ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) functions[.](#4.sentence-1)

A union shall not have
base classes[.](#4.sentence-2)

A union shall not be used as a base class[.](#4.sentence-3)

If a union contains a non-static data member of
reference type, the program is ill-formed[.](#4.sentence-4)

[*Note [3](#note-3)*:

If any non-static data member of a union has a non-trivial
copy constructor,
move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")),
copy assignment operator, or
move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
the corresponding member function
of the union must be user-provided or it will
be implicitly deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3 Deleted definitions")) for the union[.](#4.sentence-5)

[*Example [1](#example-1)*:

Consider the following union:union U {int i; float f;
 std::string s;};

Since std​::​string ([[string.classes]](string.classes "27.4 String classes")) declares non-trivial versions of all of the special
member functions, U will have an implicitly deleted
copy/move constructor and copy/move assignment operator[.](#4.sentence-7)

The default constructor and destructor of U are both trivial
even though std​::​string has
a non-trivial default constructor and a non-trivial destructor[.](#4.sentence-8)

â *end example*]

â *end note*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3258)

When the left operand of an assignment operator
involves a member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))
that nominates a union member,
it may begin the lifetime of that union member,
as described below[.](#5.sentence-1)

For an expression E,
define the set S(E) of subexpressions of E as follows:

- [(5.1)](#5.1)

  If E is of the form A.B,S(E) contains the elements of S(A),
and also contains A.B if B names a union member of a non-class, non-array type,
or of a class type with a trivial default constructor that is not deleted,
or an array of such types[.](#5.1.sentence-1)

- [(5.2)](#5.2)

  If E is of the form A[B] and is interpreted as a built-in array subscripting operator,S(E) is S(A) if A is of array type,S(B) if B is of array type,
and empty otherwise[.](#5.2.sentence-1)

- [(5.3)](#5.3)

  Otherwise, S(E) is empty[.](#5.3.sentence-1)

In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator ([[expr.assign]](expr.assign "7.6.19 Assignment and compound assignment operators"))
or a trivial assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
for each element X of S(E1) and
each anonymous union member X ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")) that
is a member of a union and
has such an element as an immediate subobject (recursively),
if modification of X would have undefined behavior under [[basic.life]](basic.life "6.8.4 Lifetime"),
an object of the type of X is implicitly created
in the nominated storage;
no initialization is performed and
the beginning of its lifetime is sequenced after
the value computation of the left and right operands
and before the assignment[.](#5.sentence-3)

[*Note [4](#note-4)*:

This ends the lifetime of the previously-active
member of the union, if any ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#5.sentence-4)

â *end note*]

[*Example [2](#example-2)*: union A { int x; int y[4]; };struct B { A a; };union C { B b; int k; };int f() { C c; // does not start lifetime of any union member c.b.a.y[3] = 4; // OK, S(c.b.a.y[3]) contains c.b and c.b.a.y;// creates objects to hold union members c.b and c.b.a.yreturn c.b.a.y[3]; // OK, c.b.a.y refers to newly created object (see [[basic.life]](basic.life "6.8.4 Lifetime"))}struct X { const int a; int b; };union Y { X x; int k; };void g() { Y y = { { 1, 2 } }; // OK, y.x is active union member ([[class.mem]](class.mem "11.4 Class members"))int n = y.x.a;
 y.k = 4; // OK, ends lifetime of y.x, y.k is active member of union y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime,// S(y.x.b) is empty because X's default constructor is deleted,// so union member y.x's lifetime does not implicitly start} â *end example*]

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3328)

[*Note [5](#note-5)*:

In cases where the above rule does not apply,
the active member of a union can only be changed by
the use of a placement [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")[.](#6.sentence-1)

â *end note*]

[*Example [3](#example-3)*:

Consider an object u of a union type U having non-static data membersm of type M and n of type N[.](#6.sentence-2)

If M has a non-trivial
destructor and N has a non-trivial constructor (for instance, if they declare or inherit
virtual functions), the active member of u can be safely switched from m ton using the destructor and placement [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") as follows:u.m.~M();new (&u.n) N;

â *end example*]
