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 |
+
|