When you compare signed and unsigned integers, you may not get the result you expect. Thanks to the six
std::cmp_* functions, there is a cure in C++20.
Maybe, you remember the rule “ES.100 Don’t mix signed and unsigned arithmetic” from the C++ Core Guidelines. I wrote a few words about it in my previous post on “Arithmetic Rules“. Today, I want to investigate this issue and compare signed and unsigned integers.
Let’s start with an unsafe comparison.
Unsafe Comparison of Integrals
Of course, there is a reason for the program name
When I execute the program, the output may not meet your expectations.
When you read the program output, you recognize -3 should be bigger than 7. You presumably know the reason. I compared a
signed x (line (1)) with an
unsigned y (line (2)). What is happening under the hood? The following program provides the answer.
In the example, I’m focusing on the less-than-operator. C++ Insights gives me the following output:
Here is what’s happening:
- The compiler transforms the expression
x < y(line 1) into
static_cast<unsigned int>(x) < y. In particular, the
xis converted to an unsigned int.
- Due to the conversion,
4'294'967'293is equal to (-3) modulo (2 to the power of 32).
- 32 is the number of bits of an unsigned
inton C++ Insights.
Thanks to C++20, we have a safe comparison of integrals.
Safe Comparison of Integrals
C++20 supports the six comparison functions for integrals:
Thanks to the six comparison functions, I can easily transform the previous program
unsafeComparison.cpp into the program
safeComparison.cpp. The new comparison functions require the header
I also used in this program the equal and not equal operators.
Thanks to GCC 10, here is the expected result:
Invoking a comparison function with a non-integral value would cause a compile-time error.
Trying to compare a
double (line (1)) and an
unsigned int (line (2)) gives the GCC 10 compiler a lengthy error message. Here is the crucial line of the error message:
The internal type-traits __is_standard_integer failed. I was curious about what that means and looked it up in the GCC type-traits implementation on GitHub. Here are the relevant lines from the header
__remove_cv_t is the internal function of GCC to remove
volatile from a type.
Maybe, you are now curious about what happens when you compare a
double and an
unsigned int the classical way.
Here is the modified program
After so many comparisons, I want to end this post with our new mathematical constants with C++20.
First, the constants require the header
<numbers> and the namespace
std::numbers. The following tables give you the first overview.
mathematicConstants.cpp applies the mathematical constants.
Here is the output of the program with the MSVC compiler 19.27.
The mathematical constants are available for
long double. Per-default
double is used, but you can also specify
long double (
C++20 offers more valuable utilities. For example, you can ask your compiler which C++ feature it supports, and can easily create functional objects with
std::bind_front, or perform different actions in a function whether the function runs a compile-time or at runtime.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,