哪种类型会使“ std :: has_unique_object_representations”返回假? [英] What type will make "std::has_unique_object_representations" return false?

查看:91
本文介绍了哪种类型会使“ std :: has_unique_object_representations”返回假?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

cppref 处,我看到了一个奇怪的类型特征检查器 std :: has_unique_object_representations



从其描述中,我无法想象任何类型的 std :: has_unique_object_representations< T> :: value 的> T 为 false



是否有任何反例?

解决方案

了解目的这种特征的理解需要理解对象值表示与其对象表示之间的区别。根据标准:


T类型的对象的对象表示 code>是由 T 类型的对象占用的N个无符号字符对象的序列,其中N等于 sizeof(T)。对象的值表示形式是持有 T 类型值的位的集合。对于平凡可复制的类型,值表示形式是对象表示形式中确定值的一组位,该值是实现定义的一组值中的一个离散元素。


因此,对象表示是对象的总存储量。但是请考虑以下对象:

  struct T 
{
char c;
int i;
};

在许多系统上, sizeof(T)将是8。为什么?因为 int 必须对齐4字节,所以编译器在 c 和<$ c之间插入了3个字节的填充。 $ c> i 。由于这三个字节是对象存储的一部分(基于 sizeof(T)),因此它们是对象的对象表示形式的一部分。



但是这三个字节不是其值表示的一部分。如果您修改了这些字节,它们将不会影响 c i 或其他任何与它们有关的值。 / p>

如果您为 T 写了 operator == 重载,更改这些字节不会影响其结果。这也意味着,如果确实编写了 operator == 重载,则无法这样实现:

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

为什么不呢?因为两个 T 的填充字节可以具有不同的值,但仍具有相同的 c i 。因此,它们具有相同的值表示形式,因此应视为等效的。



has_unique_object_representations T 的对象表示形式及其值表示形式恰好彼此重叠(并且当 T 是可复制的时)。那么,什么时候您会在意呢?



您可以编写一个通用的哈希函数,该函数适用于任何简单可复制的类型 T 通过将其值表示形式读取为字节数组并对其进行哈希处理。好吧,您可以这样做,但前提是该类型没有填充字节。这就是 has_unique_object_representations 告诉您的:对象表示形式中的所有字节都很重要。



另外,请注意, float 类型不一定具有正确的值,因为在IEEE-754中二进制相等和浮点相等并不相同。因此,包含 float 的类型也不一定一定是这样。确实,使用一个人的补码有符号整数或带有陷阱表示形式的有符号整数的实现对于这种类型也将不适用。


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 type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T . 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 Ts 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 floats 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.

这篇关于哪种类型会使“ std :: has_unique_object_representations”返回假?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆