namespace std {
struct strong_ordering { int n;
constexpr operator int() const { return n; }
static const strong_ordering less, equal, greater;
};
constexpr strong_ordering strong_ordering::less{-1},
strong_ordering::equal{0}, strong_ordering::greater{1};
struct weak_ordering {
int n;
constexpr weak_ordering(int n) : n(n) {}
constexpr weak_ordering(strong_ordering o) : n(o.n) {}
constexpr operator int() const { return n; }
static const weak_ordering less, equivalent, greater;
};
constexpr weak_ordering weak_ordering::less{-1},
weak_ordering::equivalent{0}, weak_ordering::greater{1};
struct partial_ordering {
double d;
constexpr partial_ordering(double d) : d(d) {}
constexpr partial_ordering(strong_ordering o) : d(o.n) {}
constexpr partial_ordering(weak_ordering o) : d(o.n) {}
constexpr operator double() const { return d; }
static const partial_ordering less, equivalent, greater, unordered;
};
constexpr partial_ordering partial_ordering::less{-1},
partial_ordering::equivalent{0}, partial_ordering::greater{1},
partial_ordering::unordered{__builtin_nan("")};
static_assert(!(partial_ordering::unordered < 0));
static_assert(!(partial_ordering::unordered == 0));
static_assert(!(partial_ordering::unordered > 0));
}
namespace Deletedness {
struct A {
std::strong_ordering operator<=>(const A&) const;
};
struct B {
bool operator==(const B&) const;
bool operator<(const B&) const;
};
struct C {
std::strong_ordering operator<=>(const C&) const = delete; };
struct D1 {
bool operator==(const D1&) const;
std::strong_ordering operator<=>(int) const; bool operator<(int) const; };
struct D2 {
bool operator<(const D2&) const;
std::strong_ordering operator<=>(int) const; bool operator==(int) const; };
struct E {
bool operator==(const E&) const;
bool operator<(const E&) const = delete; };
struct F {
std::strong_ordering operator<=>(const F&) const; std::strong_ordering operator<=>(F) const; };
struct G1 {
bool operator==(const G1&) const;
void operator<(const G1&) const;
};
struct G2 {
void operator==(const G2&) const;
bool operator<(const G2&) const;
};
struct H {
void operator<=>(const H&) const;
};
template<typename T> struct Cmp : T { std::strong_ordering operator<=>(const Cmp&) const = default; };
void use(...);
void f() {
use(
Cmp<A>() <=> Cmp<A>(),
Cmp<B>() <=> Cmp<B>(),
Cmp<C>() <=> Cmp<C>(), Cmp<D1>() <=> Cmp<D1>(), Cmp<D2>() <=> Cmp<D2>(), Cmp<E>() <=> Cmp<E>(), Cmp<F>() <=> Cmp<F>(), Cmp<G1>() <=> Cmp<G1>(), Cmp<G2>() <=> Cmp<G2>(), Cmp<H>() <=> Cmp<H>(), 0
);
}
template<typename T> struct CmpArray {
T arr[3]; std::strong_ordering operator<=>(const CmpArray&) const = default; };
void g() {
use(
CmpArray<A>() <=> CmpArray<A>(),
CmpArray<B>() <=> CmpArray<B>(),
CmpArray<C>() <=> CmpArray<C>(), CmpArray<D1>() <=> CmpArray<D1>(), CmpArray<D2>() <=> CmpArray<D2>(), CmpArray<E>() <=> CmpArray<E>(), CmpArray<F>() <=> CmpArray<F>(), CmpArray<G1>() <=> CmpArray<G1>(), CmpArray<G2>() <=> CmpArray<G2>(), CmpArray<H>() <=> CmpArray<H>(), 0
);
}
}
namespace Access {
class A {
std::strong_ordering operator<=>(const A &) const; public:
bool operator==(const A &) const;
bool operator<(const A &) const;
};
struct B {
A a; friend std::strong_ordering operator<=>(const B &, const B &) = default; };
class C {
std::strong_ordering operator<=>(const C &); bool operator==(const C &) const; bool operator<(const C &) const;
};
struct D {
C c; friend std::strong_ordering operator<=>(const D &, const D &) = default; };
}
namespace Synthesis {
enum Result { False, True, Mu };
constexpr bool toBool(Result R) {
if (R == Mu) throw "should not ask this question";
return R == True;
}
struct Val {
Result equal, less;
constexpr bool operator==(const Val&) const { return toBool(equal); }
constexpr bool operator<(const Val&) const { return toBool(less); }
};
template<typename T> struct Cmp {
Val val;
friend T operator<=>(const Cmp&, const Cmp&) = default; };
template<typename T> constexpr auto cmp(Result equal, Result less = Mu, Result reverse_less = Mu) {
return Cmp<T>{equal, less} <=> Cmp<T>{Mu, reverse_less};
}
static_assert(cmp<std::strong_ordering>(True) == 0);
static_assert(cmp<std::strong_ordering>(False, True) < 0);
static_assert(cmp<std::strong_ordering>(False, False) > 0);
static_assert(cmp<std::weak_ordering>(True) == 0);
static_assert(cmp<std::weak_ordering>(False, True) < 0);
static_assert(cmp<std::weak_ordering>(False, False) > 0);
static_assert(cmp<std::partial_ordering>(True) == 0);
static_assert(cmp<std::partial_ordering>(False, True) < 0);
static_assert(cmp<std::partial_ordering>(False, False, True) > 0);
static_assert(!(cmp<std::partial_ordering>(False, False, False) > 0));
static_assert(!(cmp<std::partial_ordering>(False, False, False) == 0));
static_assert(!(cmp<std::partial_ordering>(False, False, False) < 0));
struct custom_ordering {
custom_ordering(std::strong_ordering o);
};
void f(Cmp<custom_ordering> c) {
c <=> c; }
}
namespace Preference {
struct A {
A(const A&) = delete; friend void operator<=>(A, A); friend bool operator==(A, A);
friend bool operator<(A, A);
};
struct B {
B();
A a;
std::strong_ordering operator<=>(const B&) const = default; };
bool x = B() < B(); }