1 // RUN: %clang_cc1 -std=c++2a -verify %s
4 class strong_ordering
{
6 constexpr strong_ordering(int n
) : n(n
) {}
8 static const strong_ordering less
, equal
, greater
;
9 bool operator!=(int) { return n
!= 0; }
11 constexpr strong_ordering
strong_ordering::less
{-1},
12 strong_ordering::equal
{0}, strong_ordering::greater
{1};
16 constexpr weak_ordering(int n
) : n(n
) {}
18 constexpr weak_ordering(strong_ordering o
);
19 static const weak_ordering less
, equivalent
, greater
;
20 bool operator!=(int) { return n
!= 0; }
22 constexpr weak_ordering
weak_ordering::less
{-1},
23 weak_ordering::equivalent
{0}, weak_ordering::greater
{1};
25 class partial_ordering
{
27 constexpr partial_ordering(int n
) : n(n
) {}
29 constexpr partial_ordering(strong_ordering o
);
30 constexpr partial_ordering(weak_ordering o
);
31 static const partial_ordering less
, equivalent
, greater
, unordered
;
32 bool operator!=(int) { return n
!= 0; }
34 constexpr partial_ordering
partial_ordering::less
{-1},
35 partial_ordering::equivalent
{0}, partial_ordering::greater
{1},
36 partial_ordering::unordered
{2};
39 namespace DeducedNotCat
{
41 A
operator<=>(const A
&) const; // expected-note {{selected 'operator<=>' for member 'a' declared here}}
44 A a
; // expected-note {{return type 'A' of three-way comparison for member 'a' is not a standard comparison category type}}
45 auto operator<=>(const B
&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
49 namespace DeducedVsSynthesized
{
51 bool operator==(const A
&) const;
52 bool operator<(const A
&) const;
55 A a
; // expected-note {{no viable three-way comparison function for member 'a'}}
56 auto operator<=>(const B
&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
61 template<typename T
> struct wrap
{
63 friend auto operator<=>(const wrap
&, const wrap
&) = default;
66 using strong
= wrap
<int>;
67 using strong2
= wrap
<int*>;
69 friend std::weak_ordering
operator<=>(weak
, weak
);
71 using partial
= wrap
<float>;
73 template<typename
...T
> struct A
: T
... {
74 friend auto operator<=>(const A
&, const A
&) = default;
77 template<typename Expected
, typename
...Ts
> void f() {
78 using T
= Expected
; // expected-note {{previous}}
79 using T
= decltype(A
<Ts
...>() <=> A
<Ts
...>()); // expected-error {{different type}}
80 void(A
<Ts
...>() <=> A
<Ts
...>()); // trigger synthesis of body
83 template void f
<std::strong_ordering
>();
84 template void f
<std::strong_ordering
, strong
>();
85 template void f
<std::strong_ordering
, strong
, strong2
>();
87 template void f
<std::weak_ordering
, weak
>();
88 template void f
<std::weak_ordering
, weak
, strong
>();
89 template void f
<std::weak_ordering
, strong
, weak
>();
91 template void f
<std::partial_ordering
, partial
>();
92 template void f
<std::partial_ordering
, weak
, partial
>();
93 template void f
<std::partial_ordering
, strong
, partial
>();
94 template void f
<std::partial_ordering
, partial
, weak
>();
95 template void f
<std::partial_ordering
, partial
, strong
>();
96 template void f
<std::partial_ordering
, weak
, partial
, strong
>();
98 // Check that the above mechanism works.
99 template void f
<std::strong_ordering
, weak
>(); // expected-note {{instantiation of}}
101 std::strong_ordering x
= A
<strong
>() <=> A
<strong
>();
105 // Make sure we trigger return type deduction for a callee 'operator<=>'
106 // before inspecting its return type.
107 template<int> struct a
{
108 friend constexpr auto operator<=>(a
const &lhs
, a
const &rhs
) {
109 return std::strong_ordering::equal
;
113 friend constexpr auto operator<=>(b
const &, b
const &) = default;
116 std::strong_ordering cmp_b
= b() <=> b();
119 auto operator<=>(const c
&) const&; // expected-note {{selected 'operator<=>' for base class 'c' declared here}}
121 struct d
: c
{ // expected-note {{base class 'c' declared here}}
122 friend auto operator<=>(const d
&, const d
&) = default; // #d
123 // expected-error@#d {{return type of defaulted 'operator<=>' cannot be deduced because three-way comparison for base class 'c' has a deduced return type and is not yet defined}}
124 // expected-warning@#d {{implicitly deleted}}
125 // expected-note@#d {{replace 'default'}}
127 auto c::operator<=>(const c
&) const& { // #c
128 return std::strong_ordering::equal
;
130 // expected-error@+1 {{overload resolution selected deleted operator '<=>'}}
131 std::strong_ordering cmp_d
= d() <=> d();
132 // expected-note@#c 2{{candidate}}
133 // expected-note@#d {{candidate function has been implicitly deleted}}
136 namespace BadDeducedType
{
138 // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'auto &'}}
139 friend auto &operator<=>(const A
&, const A
&) = default;
143 // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'const auto'}}
144 friend const auto operator<=>(const B
&, const B
&) = default;
147 template<typename T
> struct X
{}; // expected-note {{here}}
149 // expected-error@+1 {{deduction not allowed in function return type}}
150 friend X
operator<=>(const C
&, const C
&) = default;
153 template<typename T
> concept CmpCat
= true;
155 // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'CmpCat auto'}}
156 friend CmpCat
auto operator<=>(const D
&, const D
&) = default;
162 auto operator<=>(const A
&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
163 void (*x
)(); // expected-note {{because there is no viable three-way comparison function for member 'x'}}
167 auto operator<=>(const B
&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
168 void (B::*x
)(); // expected-note {{because there is no viable three-way comparison function for member 'x'}}
172 auto operator<=>(const C
&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
173 int C::*x
; // expected-note {{because there is no viable three-way comparison function for member 'x'}}
179 operator int() const;
182 auto operator<=>(b1
const &) const = default;
185 std::strong_ordering cmp_b1
= b1() <=> b1();
188 operator float() const;
191 auto operator<=>(b2
const &) const = default;
194 std::partial_ordering cmp_b2
= b2() <=> b2();
196 using fp
= void (*)();
202 auto operator<=>(b3
const &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
203 a3 f
; // expected-note {{because there is no viable three-way comparison function}}
206 struct a4
{ // Test that function pointer conversion operator here is ignored for this overload resolution.
207 operator int() const;
211 auto operator<=>(b4
const &) const = default;
214 std::strong_ordering cmp_b4
= b4() <=> b4();