[class.union]

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

## 11.5 Unions [class.union]

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

[1](#general-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[.](#general-1.sentence-1)

[2](#general-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"))[.](#general-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[.](#general-2.sentence-2)

[*Note [1](#general-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")[.](#general-2.sentence-3)

â *end note*]

[3](#general-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[.](#general-3.sentence-1)

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

[*Note [2](#general-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"))[.](#general-3.sentence-3)

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

â *end note*]

[4](#general-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[.](#general-4.sentence-1)

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

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

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

[*Note [3](#general-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[.](#general-4.sentence-5)

[*Example [1](#general-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[.](#general-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[.](#general-4.sentence-8)

â *end example*]

â *end note*]

[5](#general-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[.](#general-5.sentence-1)

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

- [(5.1)](#general-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[.](#general-5.1.sentence-1)

- [(5.2)](#general-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[.](#general-5.2.sentence-1)

- [(5.3)](#general-5.3)

  Otherwise, S(E) is empty[.](#general-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]](#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[.](#general-5.sentence-3)

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

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

â *end note*]

[*Example [2](#general-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](#general-6)

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

[*Note [5](#general-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]")[.](#general-6.sentence-1)

â *end note*]

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

Consider an object u of a union type U having non-static data membersm of type M and n of type N[.](#general-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*]

### [11.5.2](#anon) Anonymous unions [[class.union.anon]](class.union.anon)

[1](#anon-1)

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

A union of the form

union { [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") } ;

is called an [*anonymous union*](#def:anonymous_union "11.5.2 Anonymous unions [class.union.anon]"); it defines an unnamed type and
an unnamed object of that type called
an [*anonymous union member*](#def:member,anonymous_union "11.5.2 Anonymous unions [class.union.anon]") if it is a non-static data member or
an [*anonymous union variable*](#def:variable,anonymous_union "11.5.2 Anonymous unions [class.union.anon]") otherwise[.](#anon-1.sentence-1)

Each [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of an anonymous union shall either define one or more public non-static data members or
be a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")[.](#anon-1.sentence-2)

Nested types, anonymous unions, and functions
shall not be declared within an anonymous union[.](#anon-1.sentence-3)

The names of the members of an anonymous union
are bound in the scope inhabited by the union declaration[.](#anon-1.sentence-4)

[*Example [1](#anon-example-1)*: void f() {union { int a; const char* p; };
 a = 1;
 p = "Jennifer";}

Here a and p are used like ordinary (non-member)
variables, but since they are union members they have the same address[.](#anon-1.sentence-5)

â *end example*]

[2](#anon-2)

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

An anonymous union declared in the scope of a namespace with external linkage
shall use the [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") static[.](#anon-2.sentence-1)

Anonymous unions declared at block scope shall not use a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") that is not permitted in the declaration of a block variable[.](#anon-2.sentence-2)

An anonymous union declaration at class scope shall not have
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")[.](#anon-2.sentence-3)

[3](#anon-3)

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

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

A union for which objects, pointers, or references are declared is not an anonymous union[.](#anon-3.sentence-1)

[*Example [2](#anon-example-2)*: void f() {union { int aa; char* p; } obj, *ptr = &obj;
 aa = 1; // error ptr->aa = 1; // OK}

The assignment to plain aa is ill-formed since the member name
is not visible outside the union, and even if it were visible, it is not
associated with any particular object[.](#anon-3.sentence-2)

â *end example*]

â *end note*]

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

Initialization of unions with no user-declared constructors is described
in [[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates")[.](#anon-3.sentence-3)

â *end note*]

[4](#anon-4)

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

A [*union-like class*](#def:class,union-like "11.5.2 Anonymous unions [class.union.anon]") is a union or a class that has an anonymous union as a direct
member[.](#anon-4.sentence-1)

A union-like class X has a set of [*variant members*](#def:variant_member "11.5.2 Anonymous unions [class.union.anon]")[.](#anon-4.sentence-2)

If X is a union, a non-static data member of X that is not an anonymous
union is a variant member of X[.](#anon-4.sentence-3)

In addition, a non-static data member of an
anonymous union that is a member of X is also a variant member of X[.](#anon-4.sentence-4)

At most one variant member of a union may have a default member initializer[.](#anon-4.sentence-5)

[*Example [3](#anon-example-3)*: union U {int x = 0; union {int k; }; union {int z; int y = 1; // error: initialization for second variant member of U};}; â *end example*]
