为什么C ++ 20中引入了std :: ssize()?

Joh*_* Li 92 c++ c++20

C ++ 20引入了std::ssize()free函数,如下所示:

template <class C>
    constexpr auto ssize(const C& c)
        -> std::common_type_t<std::ptrdiff_t,
                              std::make_signed_t<decltype(c.size())>>;
Run Code Online (Sandbox Code Playgroud)

似乎可以使用实现static_cast,将size()cl ass C的成员函数的返回值转换为其已签名的对应函数。

由于size()C 的成员函数始终返回非负值,为什么有人会将它们存储在带符号的变量中?万一真的要,那很简单static_cast

为什么std::ssize()在C ++ 20中引入?

Nad*_*'El 65

本文描述了基本原理。引用:

当C ++ 17中采用span时,它使用带符号整数作为索引和大小。部分原因是允许使用“ -1”作为前哨值,以指示其大小在编译时未知的类型。但是让STL容器的size()函数返回带符号的值是有问题的,因此引入了P1089来“修复”问题。它获得了多数支持,但没有获得共识所需的2比1利润。

本文P1227是一项建议,以添加非成员std :: ssize和成员ssize()函数。包含这些内容将使某些代码更加简单明了,并可以避免在大小计算中出现不必要的无符号性。这个想法是,如果通过std :: ssize()和作为成员函数使ssize()可用于所有容器,则对P1089的抵抗力将降低。

  • for(int i = 0; i &lt;container.ssize()-1; ++ i)的例子也很引人注目 (28认同)
  • @LF:是一次会议上的赫伯·萨特(也许比耶恩也这么说)。但是,他有点不对劲。现在,使用32位/ 64位计算机,签名大小会更好(因此,他是对的)。但是在过去(16位大小),带符号的大小会很糟糕(例如,我们只能分配32k字节数组)。 (15认同)
  • @ JohnZ.Li长期以来,人们一直认为STL大小类型是无符号的是一个错误。现在不幸的是,现在进行改革为时已晚。到目前为止,提供免费功能是我们所能做的最好的事情。 (13认同)
  • @LF:我发现赫伯(Herb)提到了这一点:https://www.youtube.com/watch?v=Puio5dly9N8&amp;t=2667。当他说“在实践中很少出现”时,这是正确的。但这在20年前(16位系统)根本不是真的。因此,在设计STL时使用unsigned并不是什么大错。 (11认同)
  • @John在我看来确实确实可以与string :: npos做同样的事情,只是将size_t(-1)用作特殊值。 (7认同)
  • @LF我不关注。为什么STL使用非负大小类型会被认为是错误的? (2认同)
  • @Caleth也为for(auto i = container.ssize()-1; i&gt; = 0; --i)`...也被称为每个人对无符号环绕式bug的第一个介绍。 (2认同)

sp2*_*nny 42

无偿被盗埃里克Niebler:

'Unsigned types signal that a negative index/size is not sane'最初设计STL时,这是流行的智慧。但是从逻辑上讲,事情的数量不一定是肯定的。我可能希望将计数保持为有符号整数,以表示添加到集合中或从集合中删除的元素的数量。然后,我想将其与集合的大小结合起来。如果集合的大小是无符号的,那么现在我不得不混合使用有符号和无符号算术,这是一个Bug场。编译器对此发出警告,但是由于STL的设计几乎迫使程序员陷入这种情况,因此警告非常普遍,以至于大多数人都将其关闭。真可惜,因为这掩盖了真正的错误。

在接口中使用unsigned int并不是很多人认为的福音。如果用户偶然将一个略微负数传递给API,则它突然变成一个巨大的正数。如果API将数字作为签名,则可以通过断言该数字大于或等于零来检测情况。

如果我们将无符号整数的使用限制为可旋转(例如掩码),并在其他地方使用带符号的整数,则错误发生的可能性较小,并且更容易检测到它们何时发生。

  • Swift采取了这种方法,即使它不必担心负号被重新解释为无符号的大号(因为没有隐式强制转换,这才真正使您进入这个疯狂的娱乐之家)。他们只是采用了(机器字大小的)“ Int”应该是整数的通用货币类型,即使只有正数才有意义(例如索引数组)的方法。任何偏离它的理由都应该成立。不用担心到处都有演员表是很高兴的。 (6认同)
  • Rust(最现代的系统编程语言)也使用无符号类型作为索引(因为它有意义)。C++ 简直无法修复。它是旧技术,设计不佳,几乎所有默认行为都不正确/不直观。在过去的几个版本中,C++ 所发生的一切都是对设计不佳的功能进行了糟糕的修补。 (3认同)
  • @ JohnZ.Li实际上,[“未签名的int被认为对Java有害”](https://www.nayuki.io/page/unsigned-int-considered-harmful-for-java) (2认同)