Consider the following class, which can either be in a "non-empty" or "empty" state, and in the "empty" state the other member is default initialized (hence has an indeterminate value):
struct MaybeInt {
bool has_value;
int value;
MaybeInt() : has_value(false) {}
MaybeInt(int v) : has_value(true ), value(v) {}
};
Is it allowed to assign from a default-constructed MaybeInt, as in:
MaybeInt empty, another;
another = empty; // OK?
How about construction?
MaybeInt empty, another(empty); // OK?
Does the answer change if MaybeInt::value has type char?
another = empty is indeed UB because empty.value has an indeterminate value and because the implicitly defined copy constructor of a class copies all members.
The trick is to place the member value in a union. This way the implicitly defined copy constructor of the union copies the object representation :
struct MaybeInt {
bool has_value;
union {
int value;
char _dumb;
};
MaybeInt() : has_value(false) {}
MaybeInt(int v) : has_value(true ), value(v) {}
};
NB: This is a low level trick to have an optional that is trivially copyable. This is realy important for code execution speed. This class can be passed through function call on a cpu register, while it would be impossible if it were not trivially copyable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With