At cppref, I see a weird type trait checker: std::has_unique_object_representations
From its description, I cannot imagine any type T
that make std::has_unique_object_representations<T>::value
is false
.
Is there any counter-example?
Understanding the purpose of this trait requires understanding the distinction between an objects "value representation" and its "object representation". From the standard:
The object representation of an object of type
T
is the sequence of N unsigned char objects taken up by the object of typeT
, where N equalssizeof(T)
. The value representation of an object is the set of bits that hold the value of typeT
. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.
So, object representation is the total storage of an object. But consider the following object:
struct T
{
char c;
int i;
};
On many systems, sizeof(T)
will be 8. Why? Because int
has to be 4-byte aligned, so the compiler inserts 3 bytes of padding between c
and i
. Since those three bytes are part of the object's storage (based on sizeof(T)
), they are part of the object's object representation.
But those three bytes are not part of its value representation. If you modified those bytes, they would not affect the values of c
or i
, or anything else about them.
If you wrote an operator==
overload for T
, changes to those bytes would not affect its results. Which also means that if you did write an operator==
overload, it could not be implemented like this:
bool operator==(const T &lhs, const T &rhs)
{
return std::memcmp(&lhs, &rhs, sizeof(T)) == 0;
}
Why not? Because two T
s can have different values for those padding bytes, but still have the same value of c
and i
. And thus they have the same value representation and thus should be considered equivalent.
has_unique_object_representations
is true when T
's object representation and its value representation exactly overlay one another (and when T
is trivially copyable). So, when would you care about this?
You can write a generalized hashing function that works on any trivially copyable type T
by reading its value representation as an array of bytes and hashing them. Well, you could do that, but only if the type doesn't have padding bytes. And that's what has_unique_object_representations
tells you: that all of the bytes in the object representation matter.
Also, note that float
types, won't necessarily have this value be true, since binary equality and floating-point equality aren't the same thing in IEEE-754. So types which contain float
s will also not necessarily have this be true. Indeed, implementations that use one's-complement signed integers, or signed integers with trap representations, will also not have this be true for such types.
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