为什么 C++20 的 `std::popcount` 只限于无符号类型?

huangapple go评论79阅读模式
英文:

Why is C++20's `std::popcount` restricted to unsigned types?

问题

P0553R4: 位操作 中的函数受限于仅在无符号整数上工作。该提案未说明此限制的原因。我可以理解,如果有符号整数的位表示未定义,那么这是有道理的,但是在 C++20 中,我们保证有符号整数使用二进制补码。

因此,对我来说,允许例如使用有符号整数类型调用 std::popcount 似乎是合理的,因为实现可以简单地将其强制转换为相应的无符号类型以在无符号域中执行位操作。

P0553R4 添加此约束的原因是什么?(是否仅仅是 P0553R4 和 P0907R4 之间缺乏同步?)

英文:

The functions from P0553R4: Bit operations are constrained to only work on unsigned integers. The proposal does not give a reason for this constraint. I can see that this makes sense if the bit representation of a signed integer is not defined, but with C++20, we are guaranteed that signed integers use two's complement.

To me, it thus seems reasonable to allow e.g. std::popcount to be called with a signed integer type, as an implementation could simply cast to the corresponding unsigned type to do the bit-operation in the unsigned domain.

What is the reason for P0553R4 to add this constraint? (Is it simply missing synchronization between P0553R4 and P0907R4?)

答案1

得分: 71

隐式的无符号类型的扩展转换不会改变结果。对有符号类型的隐式扩展转换(包括提升)会执行符号扩展,如果输入为负数,则会改变结果。

由于整数提升导致操作结果不正确的情况,绝对属于“踩雷”类别。

你仍然可以将(表示)负值的位模式传递给 popcount,但你必须控制转换序列,这有助于获得你期望的结果。

英文:

Pretty simple: Implicit widening conversions on unsigned types do not change the result. Implicit widening conversions on signed types (including promotions) perform sign-extension, which does change the result if the input was negative.

Having an operation whose result becomes incorrect due to integer promotion definitely falls into the "foot cannon" category.

You can still feed (bit patterns representing) negative values to popcount, but you have to take control of the conversion sequence, which helps you get the result you expect.

答案2

得分: 25

popcount 计算位数,因此需要使用作为“位容器”的类型。

  • 无符号整数类型用作位容器(或模2^n值)。
  • 有符号整数类型用作数字,稍微抽象一些。

是的,C++20以后,有符号整数保证采用二进制补码语义,但这是一个非必要的细节 - 这也是为什么直到C++20之前没有保证采用二进制补码的原因。如果你不是一个语言律师,你可能甚至不会注意到这个变化。

所以,不要试图成为一个语言律师/人类百科全书 - 不要对可能以不同方式定义的类型的确切语义做太多假设。如果你做出这样的假设 - 你可能会幸运地正确计算 popcount;但你也可能会被@BenVoigt的回答所困扰。

英文:

popcount counts bits, and hence takes a type intended for use as a "bit container".

  • unsigned integer types are intended for use as bit containers (or modulo-2^n values).
  • signed integer types are intended for use as numbers, somewhat more abstractly.

Yes, it's true that since C++20, twos-complement semantics are guaranteed for signed integers, but that's a non-essential detail - which is exactly why two's-complement wasn't guaranteed until C++20. And if you're not a language-lawyer, you are likely to not even be aware of this change.

So, instead of trying to be a language-lawyer/human encyclopedia - make less assumptions about the exact semantics of types which may have been defined otherwise. If you make such assumptions - you might luck out and popcount correctly; but you might just get bitten by @BenVoigt's answer.

<sub>See also the application of the same principle in my answer to this question.</sub>

答案3

得分: -2

popcount 在 C++20 中仅限于无符号类型,是为了确保一致的行为并避免在使用有符号整数时出现潜在问题。

在应用位操作,例如计算设置位的数量(popcount)时,对有符号整数进行操作可能会导致意外行为,这是由于符号位可能在操作期间传播,可能导致不正确的结果或未定义行为。

为了确保一致和可预测的行为,决定将 popcount 限制为无符号类型。无符号整数类型用于作为位容器,而有符号整数类型用于作为数字。通过将 popcount 限制为无符号类型,可以避免潜在问题,并确保函数在所有情况下都按预期行为。

英文:

The reason why popcount in C++20 is restricted to unsigned types is to ensure consistent behavior and avoid potential pitfalls when working with signed integers.

When applying bitwise operations, such as counting the number of set bits (popcount), on signed integers, there can be unexpected behavior due to the sign bit. The sign bit can propagate during operations, potentially leading to incorrect results or undefined behavior.

To ensure consistent and predictable behavior, the decision was made to restrict popcount to unsigned types. Unsigned integer types are intended for use as bit containers, while signed integer types are intended for use as numbers. By restricting popcount to unsigned types, it avoids potential pitfalls and ensures that the function behaves as expected in all cases.

huangapple
  • 本文由 发表于 2023年6月5日 21:56:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76407160.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定