#include <compare>
struct A
{
    int n;
    auto operator<=>(A const& other) const
    {
        if (n < other.n)
        {
            return std::strong_ordering::less;
        }
        else if (n > other.n)
        {
            return std::strong_ordering::greater;
        }
        else
        {
            return std::strong_ordering::equal;
        }
    }
    // compile error if the following code is commented out.
    // bool operator==(A const& other) const
    // { return n == other.n; }
};
int main()
{   
    A{} == A{};
}
看在线演示
为什么我必须 operator == 在 足够的时候提供operator <=> ?
c++ language-design language-lawyer spaceship-operator c++20
#include <compare>
struct A
{
    int n;
    auto operator <=>(const A&) const noexcept = default;
};
struct B
{
    int n;
    auto operator <=>(const B& rhs) const noexcept
    {
        return n <=> rhs.n;
    }
};
int main()
{
    A{} == A{}; // ok
    B{} == B{}; // error: invalid operands to binary expression
}
用 clang-10 编译为 clang -std=c++20 -stdlib=libc++ main.cpp
为什么A{} == A{}有效但无效B{} == B{}?
C++20 引入了新的太空船运算符<=>,它允许根据三向比较的排序强度来合成相等和比较运算符。
然而,当使用以下简单的玩具示例执行异构比较时,它似乎无法合成相等运算符 - 但仍然成功合成排序运算符 - 尽管具有std::strong_ordering:
#include <compare>
#include <cassert>
template <typename T>
struct Wrapper {
    int value;
    auto operator<=>(const Wrapper&) const = default;
    template <typename U>
    auto operator<=>(const Wrapper<U>& other) const {
        return value <=> other.value;
    }
};
void test() {
    // Same type equality -- works
    assert(Wrapper<Foo>{42} == Wrapper<Foo>{42});
    // Heterogeneous comparison -- works
    assert(Wrapper<Foo>{42} < Wrapper<Bar>{45});
    // Heterogeneous equality -- doesn't work?
    assert(Wrapper<Foo>{42} == Wrapper<Bar>{42});
}
在 GCC 上,这会出现以下错误:
<source>: In function …考虑这个代码:
#include <iostream>
#include <compare>
class A {
public:
  int i = {};
  std::strong_ordering operator<=> (A const& r) const
  {
    return i <=> r.i;
  }
};
void TestA()
{
    A a;
    A b;
    std::cout<< (a<b);    
    std::cout<< (a>b);
    std::cout<< (a<=b);
    std::cout<< (a>=b);
    //std::cout<< (a==b); //ERROR
    std::cout << 'E';
    //std::cout<< (a!=b); //ERROR
    std::cout << 'E';
    std::cout<< std::is_eq(a<=>b);
    std::cout<< std::is_neq(a<=>b) << std::endl;
}
class B {
public:
  int i = {};
  std::strong_ordering operator<=> (B const& r) const = default;
};
void TestB()
{ …