- If the union is CopyConstructable and Assignable, then it meets the requirements for std::vector.
- Yes:
MyUnion* ptr = new MyUnion();
- A container of pointers works in some situations, but if you want a container of owning pointers, look at Boost's ptr_* containers. However, here it appears you'd either have a container of non-pointers or a container of non-owning pointers, either of which is fine and common for vector.
All types are, by default, both CopyConstructable and Assignable. ("Copyable" is used to mean the union of these concepts, however the standard specifies them individually.) This is because copy ctors and op= are added to classes (unions are one class-type) except under certain circumstances. There are a few references online, but I'm not aware of a single one, available freely online, that spells these out.
You have to go out of your way to prevent it, such as:
- make the copy ctor or op= non-public
- make the copy ctor or op= take a non-const reference
- give the class type a non-CopyConstructable or non-Assignable member
Example:
union CopyableUnion {
int n;
char c;
double d;
};
union NonCopyableUnion {
int n;
char c;
double d;
NonCopyableUnion() {} // required, because any user-defined ctor,
// such as the private copy ctor below, prevents the supplied
// default ctor
private:
NonCopyableUnion(NonCopyableUnion const&);
NonCopyableUnion& operator=(NonCopyableUnion const&);
};
int main() {
CopyableUnion a;
CopyableUnion b = a; // fine, uses copy ctor
b = a; // fine, uses op=
NonCopyableUnion c;
NonCopyableUnion d = c; // compile error (copy ctor)
d = c; // compile error (op=)
return 0;
}
Note: And just because something is Copyable, doesn't mean it does what you want! Example:
struct A {
int* p;
A() : p(new int()) {}
// the provided copy ctor does this:
//A(A const& other) : p(other.p) {}
// which is known as "member-wise" copying
~A() { delete p; }
};
int main() {
A a;
{
A b = a;
assert(b.p == a.p); // this is a problem!
} // because when 'b' is destroyed, it deletes the same pointer
// as 'a' holds
return 0; // and now you have Undefined Behavior when
// ~A tries to delete it again
}
The same thing holds true for unions, of course. The fix applies equally, though, as well:
struct A {
int* p;
A() : p(new int()) {}
A(A const& other) : p(new int(*other.p)) {}
~A() { delete p; }
};
(If you spotted it, yes, A has a problem if you ever try to use op=, in just the same way as it originally had with the copy ctor.)