Вот они сделали, что std::strong_ordering::equal и прочие нельзя было запихнуть в switch case.
Но это не проблема, пишем враппер!
#include <compare>
enum class compare_strict {
unordered = -2,
less = -1,
greater = +1,
equal_strong = 0,
equal_weak = 2,
equal_partial = 3
};
template <typename Result>
constexpr Result cast_ordering(std::strong_ordering from) {
using t_from = decltype(from);
return from == t_from::less ? Result::less : (
from == t_from::greater ? Result::greater : Result::equal_strong
);
}
template <typename Result>
constexpr Result cast_ordering(std::weak_ordering from) {
using t_from = decltype(from);
return from == t_from::less ? Result::less : (
from == t_from::greater ? Result::greater : Result::equal_weak
);
}
template <typename Result>
constexpr Result cast_ordering(std::partial_ordering from) {
using t_from = decltype(from);
return from == t_from::less ? Result::less : (
from == t_from::greater ? Result::greater : (
from == t_from::unordered ? Result::unordered : Result::equal_partial
)
);
}
Теперь можно просто вот так:
int main() {
switch( cast_ordering<compare_strict>(0.0/0.0 <=> 1.1) ) {
case compare_strict::less :
std::cout << "less\n"; break;
case compare_strict::greater :
std::cout << "greater\n"; break;
case compare_strict::equal_partial :
std::cout << "equal_partial\n"; break;
case compare_strict::equal_weak :
std::cout << "equal_weak\n"; break;
case compare_strict::unordered :
std::cout << "unordered\n"; break;
default:
std::cout << "equal_strong\n";
}
return 0;
}
Но если вы не хотите различать equal_partial, equal_weak, equal_strong — для этого пишем ещё один enum, чтобы подставить его как Result в cast_ordering<>() :
enum class compare_simple {
less = -1,
equal_any = 0,
greater = +1,
equal_strong = equal_any,
equal_weak = equal_any,
equal_partial = equal_any,
unordered = less
};
int main() {
// Вы могли заметить, что в compare_simple ещё и unordered работает как less !
switch( cast_ordering<compare_simple>(0.0/0.0 <=> 1.1) ) {
case compare_simple::less :
std::cout << "less\n"; break;
case compare_simple::greater :
std::cout << "greater\n"; break;
case compare_simple::equal_any :
std::cout << "equal\n"; break;
default:
std::cout << "произошла фигня!\n";
}
return 0;
}
Короче таким макаром можно делать свои кастомные енумы результатов сравнения со своими значениями underlying тайпа.
Одно меня смущает однако что функция cast_ordering<>() кушает накладные расходы на трансформацию, но я думаю это не всегда критично.