// PR c++/96299 // P1186R3 // { dg-do compile { target c++20 } } #include struct H { bool operator==(H const &) const; bool operator<(H const &) const; }; // Can't deduce category from op< and op==. struct A { int i; char c; H h; // { dg-error "operator<=>" } auto operator<=>(A const &) const = default; }; // OK, explicit return type tells us how to interpret op(B const &) const = default; }; struct C { bool operator<(C const &) const; }; // C's op< isn't enough, need op== as well. struct D { C c; // { dg-error "operator<=>" } std::strong_ordering operator<=>(D const &) const = default; }; struct E { std::partial_ordering operator<=>(E const &) const; }; // Can't use a weak op<=> to build a strong op<=>. struct F { E e; // { dg-error "strong_ordering" } H h; std::strong_ordering operator<=>(F const &) const = default; }; struct G { std::strong_ordering operator<=>(G const &) const; }; // OK, uses op<=> for g and op(I const &) const = default; }; template struct J { T t; // { dg-error "no match|ambiguous" } auto operator<=>(J const &) const = default; }; template struct K { T t; // { dg-error "no match" } std::partial_ordering operator<=>(K const &) const = default; }; template struct M { T t; // { dg-error "no match|strong_ordering" } std::strong_ordering operator<=>(M const &) const = default; }; // Test that we don't fall back to is ambiguous. struct N { bool operator==(N const &) const; bool operator<(N const &) const; }; template std::partial_ordering operator<=>(N const &, T&&); template std::partial_ordering operator<=>(T&&, N const &); void foo (A &a1, A &a2, B &b1, B &b2, D& d1, D& d2, F& f1, F& f2, I& i1, I& i2) { auto a = a1 < a2; // { dg-error "deleted" } auto b = b1 < b2; auto d = d1 < d2; // { dg-error "deleted" } auto f = f1 < f2; // { dg-error "deleted" } auto i = i1 < i2; auto j1 = J() < J(); auto j2 = J() < J(); // { dg-error "deleted" } auto j3 = J() < J(); // { dg-error "deleted" } auto j4 = J() < J(); auto j5 = J() < J(); auto j6 = J() < J(); // { dg-error "deleted" } auto k1 = K() < K(); auto k2 = K() < K(); auto k3 = K() < K(); // { dg-error "deleted" } auto k4 = K() < K(); auto k5 = K() < K(); auto k6 = K() < K(); // { dg-error "deleted" } auto m1 = M() < M(); auto m2 = M() < M(); auto m3 = M() < M(); // { dg-error "deleted" } auto m4 = M() < M(); // { dg-error "deleted" } auto m5 = M() < M(); auto m6 = M() < M(); // { dg-error "deleted" } }