【问题标题】:Why does std::tuple call operator <=> twice?为什么 std::tuple 调用运算符 <=> 两次?
【发布时间】:2021-05-16 10:13:13
【问题描述】:

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

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

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

【问题讨论】:

  • @IgorR。您是在暗示 X 不是 three_way_comparable 吗?
  • 这不是意料之中的吗?它必须提供三个之一? a &lt; bb &lt; a 或相等?比如return a &lt; b ? -1 : b &lt; a ? 1 : 0,在 2/3 的情况下也需要进行 2 次比较。
  • @TedLyngmo 但是 X::operator 可以在一次调用中回答问题,这就是它存在的全部原因。
  • @RomanOdaisky 它为您生成运算符。我不明白它怎么能让一些比较消失。
  • 嗯,是的,你们可能都是对的。 :-) 我会回去做饭。

标签: c++ spaceship-operator


【解决方案1】:

简答:您需要为X 定义operator==

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

修复是单行的:

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

既然&lt;=&gt; 似乎在这里自己完成这项工作,为什么还需要==?我只能推测,但这可能是因为概念比我们习惯的更“完整”,例如只需要operator&lt;。如果一个类型可以与&lt;=&gt; 比较,那么它确实也应该支持相等性。

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

【讨论】:

    猜你喜欢
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 2014-12-19
    相关资源
    最近更新 更多