Why is std::ssize() introduced in C++20?

C++StlUnsignedSignedC++20

C++ Problem Overview


C++20 introduced the std::ssize() free function as below:

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

A possible implementation seems using static_cast, to convert the return value of the size() member function of class C into its signed counterpart.

Since the size() member function of C always returns non-negative values, why would anyone want to store them in signed variables? In case one really wants to, it is a matter of simple static_cast.

Why is std::ssize() introduced in C++20?

C++ Solutions


Solution 1 - C++

The rationale is described in this paper. A quote:

> When span was adopted into C++17, it used a signed integer both as an index and a size. Partly this was to allow for the use of "-1" as a sentinel value to indicate a type whose size was not known at compile time. But having an STL container whose size() function returned a signed value was problematic, so P1089 was introduced to "fix" the problem. It received majority support, but not the 2-to-1 margin needed for consensus. > > This paper, P1227, was a proposal to add non-member std::ssize and member ssize() functions. The inclusion of these would make certain code much more straightforward and allow for the avoidance of unwanted unsigned-ness in size computations. The idea was that the resistance to P1089 would decrease if ssize() were made available for all containers, both through std::ssize() and as member functions.

Solution 2 - C++

Gratuitously stolen from Eric Niebler:

> 'Unsigned types signal that a negative index/size is not sane' was > the prevailing wisdom when the STL was first designed. But logically, > a count of things need not be positive. I may want to keep a count in > a signed integer to denote the number of elements either added to or > removed from a collection. Then I would want to combine that with the > size of the collection. If the size of the collection is unsigned, now > I'm forced to mix signed and unsigned arithmetic, which is a bug farm. > Compilers warn about this, but because the design of the STL pretty > much forces programmers into this situation, the warning is so common > that most people turn it off. That's a shame because this hides real > bugs. > > Use of unsigned ints in interfaces isn't the boon many people think it > is. If by accident a user passes a slightly negative number to the > API, it suddenly becomes a huge positive number. Had the API taken the > number as signed, then it can detect the situation by asserting the > number is greater than or equal to zero. > > If we restrict our use of unsigned ints to bit twiddling (e.g., masks) > and use signed ints everywhere else, bugs are less likely to occur, > and easier to detect when they do occur.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn Z. LiView Question on Stackoverflow
Solution 1 - C++Nadav Har'ElView Answer on Stackoverflow
Solution 2 - C++sp2dannyView Answer on Stackoverflow