Is there a standard (or at least safe) way to compare unions for equality in C and/or C++? I expect that bitwise comparison would be useful in a number of scenarios regardless of the last-assigned member in each union; for instance, a particular bit-pattern could be reserved to mean "value is uninitialized", and it would be useful to be able to check if the union is uninitialized without needing to specify an "active" member.
An example in C++ (though I think the concept extends to C using non-member functions):
union MyData
{
public:
// Assume I'm compiling this on a platform where the size of `int`
// exceeds the size of `char*`, or that I'm using some combination
// if `#ifdef`s or similar to ensure that my numeric type is sufficiently
// large, or that I include an extra member that is known to be
// exactly the size of the larger member, just for the sake of
// comparison.
int int_member;
char* ptr_member;
bool isInitialized() const
{
return (*this != INVALID_VAL);
}
bool operator==(MyData const& rhs)
{
return / * ??? */;
}
private:
constexpr MyData INVALID_VAL { /* ??? */ };
}
// ... later, in client code...
MyData d;
bool initialized{d.isInitialized()}; // false
d.ptr_member = new char[32];
bool initialized{d.isInitialized()}; // true
Here, INVALID_VAL
could probably be defined by setting int_member
to the max negative int value, because that's an uneven value, so it won't be on a word boundary and therefore is highly unlikely to ever be assigned to the char*
member (assuming that assignments typically come directly from new
).
One possible implementation of operator==
would be simply:
return int_member == rhs.int_member;
Even though it's not known whether int_member
is the "active" member, I expect this to be safe, because I see no reason why a static cast from char*
to int
should fail or be problematic. Is that correct?
If this implementation is unsafe, something like the following should be possible (using C-style casts in C, of course):
return static_cast<void*>(*this) == static_cast<void*>(rhs);
...though of course if MyData
is larger than the size of a pointer, you'd have to start messing around with sizeof
to make this work.
Does anyone do this? Is the first (simpler) implementation safe? Is there any reason not to do it?