8

以下代码调用运算符 <=> 两次,参数颠倒。但为什么?

GCC 10.2 和 clang 12 似乎都在使用 libstdc++-10,其 <tuple> 确实提供了运算符 <=>,因此这似乎不是缺少标准库支持的情况,而且我的代码必须不正确。如何解决?

#include <tuple>
#include <compare>
#include <iostream>

struct X {
    int i;
    auto operator <=>(X const& other) const {
        std::cout << this << " <=> " << &other << std::endl;
        return i <=> other.i;
    }
};

int main() {
    std::tuple{X{42}} <=> std::tuple{X{42}};
}
4

1 回答 1

4

简短回答:您需要定义operator==for X

std::tuple<=>通过仅在类型满足时使用的综合三向比较来比较元素std::three_way_comparable_with<T,U>。最终,这需要std::three_way_comparable<X>,这需要一个说明性的weakly-equality-comparable-with概念。正如您可能猜到的那样,这需要==有效。

修复是一个单行:

bool operator==(X const& other) const = default;

现在为什么==需要在<=>这里自己完成这项工作?我只能推测,但这可能是因为概念比我们习惯的更“完整” operator<,例如只需要。如果一个类型可以与 比较<=>,它也应该支持相等。

至于为什么<=>不单独覆盖==,除非默认,这是因为相等性可以短路的类(例如向量和字符串)以及包含此类类型的任何类的性能陷阱。没有迹象表明相等性比较每个元素而不是短路,因此<=>不处理相等性,除非它可以保证您将避免该陷阱(通过 defaulting <=>)。

于 2021-02-12T17:10:13.567 回答