Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Qt use a signed integer type for its container classes?

Tags:

c++

qt

qt4

The question is clear.

I wonder why they even thought this would be handy, as clearly negative indices are unusable in the containers that would be used with them (see for example QList's docs).

I thought they wanted to allow that for some crazy form of indexing, but it seems unsupported?

It also generates a ton of (correct) compiler warnings about casting to and comparing of signed/unsigned types (on MSVC).

It just seems incompatible with the STL by design for some reason...

like image 365
rubenvb Avatar asked Feb 17 '11 14:02

rubenvb


1 Answers

Although I am deeply sympathetic to Chris's line of reasoning, I will disagree here (at least in part, I am playing devil's advocate). There is nothing wrong with using unsigned types for sizes, and it can even be beneficial in some circumstances.

Chris's justification for signed size types is that they are naturally used as array indices, and you may want to do arithmetic on array indices, and that arithmetic may create temporary values that are negative.

That's fine, and unsigned arithmetic introduces no problem in doing so, as long as you make sure to interpret your values correctly when you do comparisons. Because the overflow behavior of unsigned integers is fully specified, temporary overflows into the negative range (or into huge positive numbers) do not introduce any error as long as they are corrected before a comparison is performed.

Sometimes, the overflow behavior is even desirable, as the overflow behavior of unsigned arithmetic makes certain range checks expressible as a single comparison that would require two comparisons otherwise. If I want to check if x is in the range [a,b] and all the values are unsigned, I can simply do:

if (x - a < b - a) {
}

That doesn't work with signed variables; such range checks are pretty common with sizes and array offsets.

I mentioned before that a benefit is that overflow arithmetic has defined results. If your index arithmetic overflows a signed type, the behavior is implementation defined; there is no way to make your program portable. Use an unsigned type and this problem goes away. Admittedly this only applies to huge offsets, but it is a concern for some uses.

Basically, the objections to unsigned types are frequently overstated. The real problem is that most programmers don't really think about the exact semantics of the code they write, and for small integer values, signed types behave more nearly in line with their intuition. However, data sizes grow pretty fast. When we deal with buffers or databases, we're frequently way outside of the range of "small", and signed overflow is far more problematic to handle correctly than is unsigned overflow. The solution is not "don't use unsigned types", it is "think carefully about the code you are writing, and make sure you understand it".

like image 54
Stephen Canon Avatar answered Sep 28 '22 10:09

Stephen Canon