The new <=>
operator makes writing code more convenient and it can save some performance if the comparison algorithm is non-trivial, because it doesn't need to be repeated two times to get the full ordering.
Or at least I though so when I learned about it.
However, when I try to use it in practice, in a switch
statement, it doesn't work.
This code doesn't compile:
#include <iostream>
void compare_values(int x, int y)
{
switch (x <=> y)
{
case std::strong_ordering::less:
std::cout << "is less\n";
break;
case std::strong_ordering::greater:
std::cout << "is greater\n";
break;
case std::strong_ordering::equal:
std::cout << "is equal\n";
break;
}
}
The compiler shows an error suggesting that the value returned by <=>
cannot be used in a switch
:
<source>: In function 'void compare_values(int, int)':
<source>:5:15: error: switch quantity not an integer
5 | switch (x <=> y)
| ~~^~~~~
Compiler returned: 1
I would guess that using the spaceship operator in switch is a pretty basic, obvious and common use case, so there is probably some trick to making it work. I cannot figure it out, though.
How can I fix this code?
The problem is that the spaceship operator (formally known as three-way comparison) does not return an ingeral type, and therefore cannot be used in a switch-case
statement.
In this case of comparing types like int
s, the spaceship operator returns a std::strong_ordering
.
(A side note: as you can see in the documentation there are cases where the spaceship operator returns a std::partial_ordering
but this isn't an integral type either).
You can use it in an if-else
statement instead.
If you prefer to use a switch-case
, you can use a trivial utility that converts the std::strong_ordering
to an integral type with some predefined values.
Returning -1/0/1 in this case will be quite natural:
#include <iostream>
constexpr int strong_ordering_to_int(std::strong_ordering o)
{
if (o == std::strong_ordering::less) return -1;
if (o == std::strong_ordering::greater) return 1;
return 0;
}
void compare_values(int x, int y)
{
switch (strong_ordering_to_int(x <=> y))
{
case -1:
std::cout << "is less\n";
break;
case 1:
std::cout << "is greater\n";
break;
case 0:
std::cout << "is equal\n";
break;
}
}
int main()
{
compare_values(2, 3);
compare_values(3, 2);
compare_values(3, 3);
}
Output:
is less
is greater
is equal