blob: a979fcb65dfdd603d003806a4ace5ad4eabc1d5e [file] [log] [blame]
// PR c++/96299
// P1186R3
// { dg-do compile { target c++20 } }
#include <compare>
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</==.
struct B {
int i;
char c;
H h;
std::strong_ordering operator<=>(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</op== for h.
struct I {
G g;
H h;
std::partial_ordering operator<=>(I const &) const = default;
};
template <class T>
struct J {
T t; // { dg-error "no match|ambiguous" }
auto operator<=>(J const &) const = default;
};
template <class T>
struct K {
T t; // { dg-error "no match" }
std::partial_ordering operator<=>(K const &) const = default;
};
template <class T>
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 </== if <=> is ambiguous.
struct N {
bool operator==(N const &) const;
bool operator<(N const &) const;
};
template <class T>
std::partial_ordering operator<=>(N const &, T&&);
template <class T>
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<int>() < J<int>();
auto j2 = J<H>() < J<H>(); // { dg-error "deleted" }
auto j3 = J<C>() < J<C>(); // { dg-error "deleted" }
auto j4 = J<E>() < J<E>();
auto j5 = J<G>() < J<G>();
auto j6 = J<N>() < J<N>(); // { dg-error "deleted" }
auto k1 = K<int>() < K<int>();
auto k2 = K<H>() < K<H>();
auto k3 = K<C>() < K<C>(); // { dg-error "deleted" }
auto k4 = K<E>() < K<E>();
auto k5 = K<G>() < K<G>();
auto k6 = K<N>() < K<N>(); // { dg-error "deleted" }
auto m1 = M<int>() < M<int>();
auto m2 = M<H>() < M<H>();
auto m3 = M<C>() < M<C>(); // { dg-error "deleted" }
auto m4 = M<E>() < M<E>(); // { dg-error "deleted" }
auto m5 = M<G>() < M<G>();
auto m6 = M<N>() < M<N>(); // { dg-error "deleted" }
}