From Jason Turner

[class.union.general]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpyepna2_b/{from.md → to.md} +138 -0
tmp/tmpyepna2_b/{from.md → to.md} RENAMED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### General <a id="class.union.general">[[class.union.general]]</a>
2
+
3
+ A *union* is a class defined with the *class-key* `union`.
4
+
5
+ In a union, a non-static data member is *active* if its name refers to
6
+ an object whose lifetime has begun and has not ended [[basic.life]]. At
7
+ most one of the non-static data members of an object of union type can
8
+ be active at any time, that is, the value of at most one of the
9
+ non-static data members can be stored in a union at any time.
10
+
11
+ [*Note 1*: One special guarantee is made in order to simplify the use
12
+ of unions: If a standard-layout union contains several standard-layout
13
+ structs that share a common initial sequence [[class.mem]], and if a
14
+ non-static data member of an object of this standard-layout union type
15
+ is active and is one of the standard-layout structs, it is permitted to
16
+ inspect the common initial sequence of any of the standard-layout struct
17
+ members; see  [[class.mem]]. — *end note*]
18
+
19
+ The size of a union is sufficient to contain the largest of its
20
+ non-static data members. Each non-static data member is allocated as if
21
+ it were the sole member of a non-union class.
22
+
23
+ [*Note 2*: A union object and its non-static data members are
24
+ pointer-interconvertible [[basic.compound]], [[expr.static.cast]]. As a
25
+ consequence, all non-static data members of a union object have the same
26
+ address. — *end note*]
27
+
28
+ A union can have member functions (including constructors and
29
+ destructors), but it shall not have virtual [[class.virtual]] functions.
30
+ A union shall not have base classes. A union shall not be used as a base
31
+ class. If a union contains a non-static data member of reference type
32
+ the program is ill-formed.
33
+
34
+ [*Note 3*:
35
+
36
+ Absent default member initializers [[class.mem]], if any non-static data
37
+ member of a union has a non-trivial default constructor
38
+ [[class.default.ctor]], copy constructor, move constructor
39
+ [[class.copy.ctor]], copy assignment operator, move assignment operator
40
+ [[class.copy.assign]], or destructor [[class.dtor]], the corresponding
41
+ member function of the union must be user-provided or it will be
42
+ implicitly deleted [[dcl.fct.def.delete]] for the union.
43
+
44
+ [*Example 1*:
45
+
46
+ Consider the following union:
47
+
48
+ ``` cpp
49
+ union U {
50
+ int i;
51
+ float f;
52
+ std::string s;
53
+ };
54
+ ```
55
+
56
+ Since `std::string` [[string.classes]] declares non-trivial versions of
57
+ all of the special member functions, `U` will have an implicitly deleted
58
+ default constructor, copy/move constructor, copy/move assignment
59
+ operator, and destructor. To use `U`, some or all of these member
60
+ functions must be user-provided.
61
+
62
+ — *end example*]
63
+
64
+ — *end note*]
65
+
66
+ When the left operand of an assignment operator involves a member access
67
+ expression [[expr.ref]] that nominates a union member, it may begin the
68
+ lifetime of that union member, as described below. For an expression
69
+ `E`, define the set S(E) of subexpressions of `E` as follows:
70
+
71
+ - If `E` is of the form `A.B`, S(E) contains the elements of S(A), and
72
+ also contains `A.B` if `B` names a union member of a non-class,
73
+ non-array type, or of a class type with a trivial default constructor
74
+ that is not deleted, or an array of such types.
75
+ - If `E` is of the form `A[B]` and is interpreted as a built-in array
76
+ subscripting operator, S(E) is S(A) if `A` is of array type, S(B) if
77
+ `B` is of array type, and empty otherwise.
78
+ - Otherwise, S(E) is empty.
79
+
80
+ In an assignment expression of the form `E1 = E2` that uses either the
81
+ built-in assignment operator [[expr.ass]] or a trivial assignment
82
+ operator [[class.copy.assign]], for each element `X` of S(`E1`), if
83
+ modification of `X` would have undefined behavior under  [[basic.life]],
84
+ an object of the type of `X` is implicitly created in the nominated
85
+ storage; no initialization is performed and the beginning of its
86
+ lifetime is sequenced after the value computation of the left and right
87
+ operands and before the assignment.
88
+
89
+ [*Note 4*: This ends the lifetime of the previously-active member of
90
+ the union, if any [[basic.life]]. — *end note*]
91
+
92
+ [*Example 2*:
93
+
94
+ ``` cpp
95
+ union A { int x; int y[4]; };
96
+ struct B { A a; };
97
+ union C { B b; int k; };
98
+ int f() {
99
+ C c; // does not start lifetime of any union member
100
+ c.b.a.y[3] = 4; // OK, S(c.b.a.y[3]) contains c.b and c.b.a.y;
101
+ // creates objects to hold union members c.b and c.b.a.y
102
+ return c.b.a.y[3]; // OK, c.b.a.y refers to newly created object (see [basic.life])
103
+ }
104
+
105
+ struct X { const int a; int b; };
106
+ union Y { X x; int k; };
107
+ void g() {
108
+ Y y = { { 1, 2 } }; // OK, y.x is active union member[class.mem]
109
+ int n = y.x.a;
110
+ y.k = 4; // OK, ends lifetime of y.x, y.k is active member of union
111
+ y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime,
112
+ // S(y.x.b) is empty because X's default constructor is deleted,
113
+ // so union member y.x's lifetime does not implicitly start
114
+ }
115
+ ```
116
+
117
+ — *end example*]
118
+
119
+ [*Note 5*: In cases where the above rule does not apply, the active
120
+ member of a union can only be changed by the use of a placement
121
+ *new-expression*. — *end note*]
122
+
123
+ [*Example 3*:
124
+
125
+ Consider an object `u` of a `union` type `U` having non-static data
126
+ members `m` of type `M` and `n` of type `N`. If `M` has a non-trivial
127
+ destructor and `N` has a non-trivial constructor (for instance, if they
128
+ declare or inherit virtual functions), the active member of `u` can be
129
+ safely switched from `m` to `n` using the destructor and placement
130
+ *new-expression* as follows:
131
+
132
+ ``` cpp
133
+ u.m.~M();
134
+ new (&u.n) N;
135
+ ```
136
+
137
+ — *end example*]
138
+