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


99

C ++ 20引入了以下std::ssize()免费功能:

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

似乎可以使用实现static_cast,将size()cl ass C的成员函数的返回值转换为其有符号的对等。

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

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


4
@ Jarod42它的实现不是已定义而是未定义吗?(符号溢出是未定义的,但被定义符号的转换的实现。)
PHON

8
如果他们也添加ssizeof运算符。
盖萨

3
这可能是有点关系:stackoverflow.com/questions/30395205/...
Marco13

10
@ JohnZ.Li听起来太不确定:我认为有关整数类型的C ++的整个类型系统已损坏。当然,可以说有些古怪(例如不知道a char有多少位)是从C继承的,至少被减轻了一点(u)intX_t,但这仍然是源源不断的同样细微关键的错误。诸如此类ssize的东西只是补丁,将需要一段时间(也许是“永远”),直到它陷入人们(可以)严格遵循的通用“最佳实践指南”中。
Marco13

6
@ Marco13:另一方面,C / C ++类型系统(与Java的固定类型系统相对)除了允许C / C ++代码在大多数其他语言无法理解的体系结构上工作外,可以使合格的讲师获得一些重要的信息教训进入学生的脑海。就像,不是所有的世界都是64位的。不,并非全世界都使用8位字符。它是死很容易应付这些事情,而且这会让你成为更好的开发,如果仅仅导师会教这从一开始。(而且,只是为了确保,你知道(u)intX_t类型是可选的,你呢?)
DevSolar

Answers:


69

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

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

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


30
这个for(int i = 0; i < container.ssize() - 1; ++i)例子也很引人注目
-Caleth,

7
@John在我看来确实确实可以与string :: npos做同样的事情,只是使用size_t(-1)作为特殊值。
rubenvb

15
@ JohnZ.Li长期以来,人们一直认为STL大小类型是无符号的是一个错误。现在不幸的是,现在进行改革为时已晚。到目前为止,提供免费功能是我们所能做的最好的事情。
LF

16
@LF:是会议上的赫伯·萨特(也许比耶恩也这么说)。但是,他有点不对劲。现在,对于32位/ 64位计算机,签名大小会更好(所以他是对的)。但是在过去(16位大小),带符号的大小会很糟糕(例如,我们只能分配32k字节数组)。
盖萨

11
@LF:我发现Herb提到了这一点:youtube.com/watch ? v=Puio5dly9N8&t=2667 。当他说“在实践中很少出现”时,这是正确的。但这在20年前(16位系统)根本不是真的。因此,在设计STL时使用unsigned并不是什么大错。
盖萨

50

无偿被盗埃里克Niebler:

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

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

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


6
尽管不必担心负号会被重新解释为大量的无符号数,但Swift还是采用了这种方法(因为没有隐式强制转换,这实际上会让您进入这个疯狂的娱乐之家)。他们只是采用了方法(机器字大小)Int应该是整数的通用货币类型,即使只有正数才有意义(例如索引数组)。任何偏离它的理由都应该成立。不用担心到处都有演员表是很高兴的。
亚历山大-恢复莫妮卡

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.