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
来实现,将cl ass C 的size()
成员函数的返回值转换为其已签名的对应值。
由于C的size()
成员函数总是返回非负值,所以为什么有人要将它们存储在带符号的变量中?万一真的想要,那只是简单的static_cast
问题。
为什么在C ++ 20中引入了std::ssize()
?
答案 0 :(得分:53)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1227r1.html中描述了基本原理。引号:
在C ++ 17中采用span时,它使用带符号整数作为索引和大小。部分原因是允许使用“ -1”作为前哨值,以指示其大小在编译时未知的类型。但是让STL容器的size()函数返回带符号的值是有问题的,因此引入了P1089来“修复”问题。它获得了多数支持,但没有获得共识所需的2比1利润。
本文P1227是一项建议,以添加非成员std :: ssize和成员ssize()函数。包含这些内容将使某些代码更加简单明了,并可以避免在大小计算中出现不必要的无符号性。这个想法是,如果通过std :: ssize()和作为成员函数将ssize()用于所有容器,则对P1089的抵抗力将降低。
答案 1 :(得分:38)
由埃里克·尼布勒(Eric Niebler)感激地stolen:
'Unsigned types signal that a negative index/size is not sane'
原为 最初设计STL时的普遍智慧。但从逻辑上讲 事情不一定是积极的。我可能想保持计数 一个有符号整数,表示添加到或中的元素数 从集合中删除。然后,我想将其与 集合的大小。如果集合的大小是无符号的,现在 我被迫混合使用有符号和无符号算法,这是一个Bug场。 编译器对此有所警告,但是因为STL的设计相当漂亮 迫使程序员陷入这种情况的警告如此普遍 大多数人将其关闭。很遗憾,因为这隐藏了真实的 错误。在接口中使用无符号整数并不是很多人认为的福音 是。如果用户偶然将一个略微负数传递给 API,它突然变成了一个巨大的正数。 API是否采用了 编号,然后可以通过断言 数字大于或等于零。
如果我们将对无符号整数的使用限制为可旋转(例如,掩码) 并在其他地方使用带符号的整数,则错误发生的可能性较小, 并且更容易检测它们何时发生。