Same way you resolve any other function which returns auto in which different return statements deduce differently. You either:
- Ensure that all the
returns have the same type, or
- Explicitly pick a return type.
In this case, ints compare as strong_ordering while doubles compare as partial_ordering, and strong_ordering is implicitly convertible to partial_ordering, you can do either:
std::partial_ordering operator <=>(const QVariant& l, const QVariant& r) {
// rest as before
}
or explicitly cast the integer comparison:
case QMetaType::Int:
return std::partial_ordering(l.toInt() <=> r.toInt());
That gives you a function returning partial_ordering.
If you want to return strong_ordering instead, you have to lift the double comparison to a higher category. You can do that in two ways:
You can use std::strong_order, which is a more expensive operation, but provides a total ordering over all floating point values. You would then write:
case QMetaType::Double:
return std::strong_order(l.toDouble(), r.toDouble());
Or you can do something like consider NaNs ill-formed and throw them out somehow:
case QMetaType::Double: {
auto c = l.toDouble() <=> r.toDouble();
if (c == std::partial_ordering::unordered) {
throw something;
} else if (c == std::partial_ordering::less) {
return std::strong_ordering::less;
} else if (c == std::partial_ordering::equivalent) {
return std::strong_ordering::equal;
} else {
return std::strong_ordering::greater;
}
}
It's more tedious but I'm not sure if there's a more direct way to do this kind of lifting.