如何在 switch 语句中使用 spaceship 运算符

NO_*_*AME 6 c++ switch-statement spaceship-operator c++20

新的<=>运算符使编写代码更加方便,并且如果比较算法不平凡,它可以节省一些性能,因为它不需要重复两次才能获得完整的排序。

或者至少当我了解到这一点时我是这么认为的。然而,当我尝试在实践中使用它时,在switch声明中,它不起作用。

此代码无法编译:

#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;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器显示错误,提示返回的值<=>不能在 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
Run Code Online (Sandbox Code Playgroud)

活生生的例子

我猜想在 switch 中使用 spaceship 操作符是一个非常基本、明显和常见的用例,所以可能有一些技巧可以让它工作。但我无法弄清楚。

我该如何修复此代码?

woh*_*tad 7

问题是太空船运算符(正式名称为三向比较不返回整数类型,因此不能在语句中使用switch-case

在比较 s 这样的类型的情况下int,太空船运算符返回 a std::strong_ordering

(附注:正如您在文档中所看到的,在某些情况下,太空飞船运算符会返回 a std::partial_ordering,但这也不是整数类型)。

您可以在语句中使用它if-else

如果您更喜欢使用 a switch-case,则可以使用一个简单的实用程序将 a 转换std::strong_ordering为具有一些预定义值的整数类型。
在这种情况下返回 -1/0/1 是很自然的:

#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);
}
Run Code Online (Sandbox Code Playgroud)

输出:

is less
is greater
is equal
Run Code Online (Sandbox Code Playgroud)

现场演示

  • @TanveerBadar——不参与标准化的人很容易毫无根据地将各种愚蠢归咎于那些从事实际工作的人。 (9认同)
  • 我很难相信委员会在设计这个操作符时没有考虑到“switch”。 (3认同)
  • 如果不是因为所谓的“协同例程”这一令人厌恶的东西,我会更倾向于相信这种对细节的关注,它的唯一目的是祝福不会在 Microsoft Windows 上糟糕的线程模型。 (3认同)
  • 我的几位同事都是委员会成员,对细节的审查和痛苦令人难以置信。这就是为什么像 Stepanov 的 STL、Zverovich 的 fmt、Niebler 的范围和各种 Boost 组件这样经常(不可避免地?)标准化的东西是原始基础的子集,并且它们的语义被调整或整体改变,以便该提案适合 C++ 语言目标和北极星。 (2认同)