具有不一致排序推导的三向比较运算符

前段时间我定义了我的第一个三向比较运算符。它比较了单一类型并取代了多个常规运算符。很棒的功能。然后我尝试实现一个类似的运算符来通过委托比较两个变体:

auto operator <=> (const QVariant& l, const QVariant& r)
{   
   switch (l.type())
   {
      case QMetaType::Int:
         return l.toInt() <=> r.toInt();
      case QMetaType::Double:
         return l.toDouble() <=> r.toDouble();
      default:
         throw;
   }
}

这不能编译,我收到错误

自动返回类型的不一致扣除:“std::strong_ordering”然后是“std::partial_ordering”。

显然intdouble飞船运营商返回的类型不同。

解决这个问题的正确方法是什么?

回答

以相同的方式解析任何其他返回auto不同return语句推导出不同的函数。你要么:

  1. 确保所有的returns 都具有相同的类型,或者
  2. 显式选择返回类型。

在这种情况下,ints 比较为strong_orderingwhile doubles 比较为partial_ordering,并且strong_ordering可以隐式转换为partial_ordering,您可以执行以下任一操作:

std::partial_ordering operator <=>(const QVariant& l, const QVariant& r) {
    // rest as before
}

或显式转换整数比较:

      case QMetaType::Int:
         return std::partial_ordering(l.toInt() <=> r.toInt());

这为您提供了一个返回partial_ordering.


如果您想返回strong_ordering,则必须将double比较提升到更高的类别。您可以通过两种方式做到这一点:

您可以使用std::strong_order,这是一个更昂贵的操作,但提供所有浮点值的总排序。然后你会写:

      case QMetaType::Double:
         return std::strong_order(l.toDouble(), r.toDouble());

或者你可以做一些像 think NaNs 格式错误的事情,然后以某种方式把它们扔掉:

      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;
         }
      }

这更乏味,但我不确定是否有更直接的方法来进行这种提升。


以上是具有不一致排序推导的三向比较运算符的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>