What type will make "std :: has_unique_object_representations" return false?

In cppref, I see a strange check for signs like : std::has_unique_object_representations

From his description, I cannot imagine any type of T that std::has_unique_object_representations<T>::value false does.

Is there any counter example?

+7
c ++ standards typetraits c ++ 17
source share
1 answer

Understanding the purpose of this trait requires understanding the difference between the representation of the value of an object and its "representation of an object." From the standard:

The object representation of an object of type T is a sequence of N unsigned char objects occupied by an object of type T , where N is equal to sizeof(T) . A representation of an object value is a collection of bits that contain a value of type T For trivially copied types, a value representation is a set of bits in an object representation that defines a value that is one discrete element of a particular set of values.

So, the representation of an object is the shared memory of the object. But consider the following object:

 struct T { char c; int i; }; 

On many systems, sizeof(T) will be 8. Why? Since int must be aligned by 4 bytes, so the compiler inserts 3 bytes of padding between c and i . Since these three bytes are part of the object store (based on sizeof(T) ), they are part of the representation of the object object.

But these three bytes are not part of its representation of values. If you change these bytes, they will not affect the values ​​of c or i , or anything else about them.

If you wrote operator== overload for T , changes in these bytes will not affect its results. It also means that if you write operator== overload, it cannot be implemented as follows:

 bool operator==(const T &lhs, const T &rhs) { return std::memcmp(&lhs, &rhs, sizeof(T)) == 0; } 

Why not? Since the two T can have different values ​​for these padding bytes, but still have the same value c and i . And therefore, they have the same representation of values ​​and, therefore, should be considered equivalent.

has_unique_object_representations true when the representation of the object T and its representation of the value exactly overlap (and when T can be trivially copied). So, when would you take care of this?

You can write a generic hash function that works on any trivially copied type T by reading its representation of the value as an array of bytes and hashing them. Well, you can do this, but only if the type does not have padding bytes. And what has_unique_object_representations tells you: all bytes in the representation of the object matter.

Also note that float types will not necessarily have this value as true, since binary equality and floating point equality do not match IEEE-754. Therefore, types containing a float will also not necessarily have this value. In fact, implementations that use signed integers with signed or signed integers with traps will also not be so valid for such types.

+9
source share

All Articles