These operators do not perform lexicographical comparisons and seem to provide inconsistent results.
#include <iostream>
int main () {
std::cout << ("70" < "60") << '\n';
std::cout << ("60" < "70") << '\n';
return 0;
}
and
#include <iostream>
int main() {
std::cout << ("60" < "70") << '\n';
std::cout << ("70" < "60") << '\n';
return 0;
}
both print
1
0
The same holds true for std::less<>()
. However, std::less<std::string>()
provides the correct lexicographical comparison. What is the reason for this behaviour?
Are the comparisons shown above comparing the addresses of char arrays?
Character literals are character arrays. You are comparing these arrays, which after array-to-pointer decay means you are comparing the addresses of the first byte of these arrays.
Each character literal may refer to a different such array, even if it has the same value. And there is no guarantee about the order of their addresses.
So any possible outcome for your tests is allowed. 0
/0
as well as 0
/1
, 1
/0
and 1
/1
.
You can avoid all the C-style array behavior of string literals by always using std::string
or std::string_view
literals instead:
#include <iostream>
using namespace std::string_literals;
int main () {
std::cout << ("70"s < "60"s) << '\n';
std::cout << ("60"s < "70"s) << '\n';
return 0;
}
This uses the user-defined string literal operator""s
from the standard library to immediately form std::string
s from the string literals. sv
can be used for std::string_view
s instead. (string_view
will incur less performance cost, in particular no dynamic allocation.)