Today, I have discovered a very simple (but yet very efficient and useful) feature from C++20: the std::cmp_*
functions. They allow to compare 2 integers, which can have different signedness, without getting bitten by implicit conversions.
Let's have look at this piece of code:
#include <iostream>
int main()
{
int a = -6;
unsigned int b = 3;
if (a < b) {
std::cout << "OK: a is lower than b\n";
} else {
std::cout << "Oopsi!\n";
}
}
Yes, you've guessed right: it prints "Oopsi!".
Why?
Rule RSPEC-6214 from Sonar explains the issue very well:
Comparison between signed and unsigned integers is dangerous because it produces counterintuitive results outside of their common range of values.
When a signed integer is compared to an unsigned one, the former might be converted to unsigned. The conversion preserves the two’s-complement bit pattern of the signed value that often corresponds to a large unsigned result. For example, 2U < -1 is true.
C++20 introduced remedy to this common pitfall: a family of std::cmp_* functions defined in the header. These functions correctly handle negative numbers and lossy integer conversion. For example, std::cmp_less(2U, -1) is false.
This rule reports comparisons between signed and unsigned integers that involve negative numbers.
Let's try:
#include <iostream>
#include <utility>
int main()
{
int a = -6;
unsigned int b = 3;
if (std::cmp_less(a, b)) {
std::cout << "OK: a is lower than b\n";
} else {
std::cout << "Oopsi!\n";
}
}
And now the code prints "OK: a is lower than b" 😁
Note that your compiler can emits warnings about conversions like this. With GCC, the option -Wall
is enough:
<source>: In function 'int main()':
<source>:10:11: warning: comparison of integer expressions of different signedness: 'int' and 'unsigned int' [-Wsign-compare]
10 | if (a == b) {
| ~~^~~~
The problem is the same in C but -Wall
doesn't add -Wsign-compare
for C, only in C++.
PS: my first article on dev.to was about funny integers conversions (but you must speak French to read it 😅)
Top comments (1)
the only thing I dont like about C++ is for every class you have to create its HEADER file. else everything is great