2 // { dg-do compile { target c++23 } }
4 // well-formed and ill-formed uses of non-member capable operators in a requires expression
6 #include "explicit-obj-ops-non-mem.h"
8 // we only need the structs from the header
10 #undef VALIDATE_RETURN_TYPES
12 // It's very hard to test for incorrect successes without requires, and by extension a non dependent variable
13 // so for the time being, there are no non dependent tests invalid calls.
15 template<typename T, typename U>
16 concept same_as = __is_same(T, U);
18 #define TEST_INVALID(OPERAND, CORRECT_TYPE) \
19 static_assert(!requires{ (OPERAND) += 0; }, "Unexpected success calling operator += with " #OPERAND); \
20 static_assert(!requires{ (OPERAND) -= 0; }, "Unexpected success calling operator -= with " #OPERAND); \
21 static_assert(!requires{ (OPERAND) *= 0; }, "Unexpected success calling operator *= with " #OPERAND); \
22 static_assert(!requires{ (OPERAND) /= 0; }, "Unexpected success calling operator /= with " #OPERAND); \
23 static_assert(!requires{ (OPERAND) %= 0; }, "Unexpected success calling operator %= with " #OPERAND); \
24 static_assert(!requires{ (OPERAND) &= 0; }, "Unexpected success calling operator &= with " #OPERAND); \
25 static_assert(!requires{ (OPERAND) |= 0; }, "Unexpected success calling operator |= with " #OPERAND); \
26 static_assert(!requires{ (OPERAND) ^= 0; }, "Unexpected success calling operator ^= with " #OPERAND); \
27 static_assert(!requires{ (OPERAND) <<= 0; }, "Unexpected success calling operator <<= with " #OPERAND); \
28 static_assert(!requires{ (OPERAND) >>= 0; }, "Unexpected success calling operator >>= with " #OPERAND); \
30 static_assert(!requires{ ++(OPERAND); }, "Unexpected success calling operator pre++ with " #OPERAND); \
31 static_assert(!requires{ --(OPERAND); }, "Unexpected success calling operator pre-- with " #OPERAND); \
32 static_assert(!requires{ (OPERAND)++; }, "Unexpected success calling operator post++ with " #OPERAND); \
33 static_assert(!requires{ (OPERAND)--; }, "Unexpected success calling operator post-- with " #OPERAND); \
35 static_assert(!requires{ +(OPERAND); }, "Unexpected success calling operator unary+ with " #OPERAND); \
36 static_assert(!requires{ -(OPERAND); }, "Unexpected success calling operator unary- with " #OPERAND); \
37 static_assert(!requires{ (OPERAND) + 0; }, "Unexpected success calling operator binary+ with " #OPERAND); \
38 static_assert(!requires{ (OPERAND) - 0; }, "Unexpected success calling operator binary- with " #OPERAND); \
39 static_assert(!requires{ (OPERAND) * 0; }, "Unexpected success calling operator binary* with " #OPERAND); \
40 static_assert(!requires{ (OPERAND) / 0; }, "Unexpected success calling operator / with " #OPERAND); \
41 static_assert(!requires{ (OPERAND) % 0; }, "Unexpected success calling operator % with " #OPERAND); \
42 static_assert(!requires{ (OPERAND) & 0; }, "Unexpected success calling operator binary& with " #OPERAND); \
43 static_assert(!requires{ (OPERAND) | 0; }, "Unexpected success calling operator | with " #OPERAND); \
44 static_assert(!requires{ (OPERAND) ^ 0; }, "Unexpected success calling operator ^ with " #OPERAND); \
45 static_assert(!requires{ (OPERAND) << 0; }, "Unexpected success calling operator << with " #OPERAND); \
46 static_assert(!requires{ (OPERAND) >> 0; }, "Unexpected success calling operator >> with " #OPERAND); \
48 static_assert(!requires{ !(OPERAND); }, "Unexpected success calling operator ! with " #OPERAND); \
49 static_assert(!requires{ (OPERAND) && 0; }, "Unexpected success calling operator && with " #OPERAND); \
50 static_assert(!requires{ (OPERAND) || 0; }, "Unexpected success calling operator || with " #OPERAND); \
52 static_assert(!requires{ (OPERAND) == 0; }, "Unexpected success calling operator == with " #OPERAND); \
53 static_assert(!requires{ (OPERAND) != 0; }, "Unexpected success calling operator != with " #OPERAND); \
54 static_assert(!requires{ (OPERAND) < 0; }, "Unexpected success calling operator < with " #OPERAND); \
55 static_assert(!requires{ (OPERAND) > 0; }, "Unexpected success calling operator > with " #OPERAND); \
56 static_assert(!requires{ (OPERAND) <= 0; }, "Unexpected success calling operator <= with " #OPERAND); \
57 static_assert(!requires{ (OPERAND) >= 0; }, "Unexpected success calling operator >= with " #OPERAND); \
58 static_assert(!requires{ (OPERAND) <=> 0; }, "Unexpected success calling operator <=> with " #OPERAND); \
60 static_assert(!requires{ *(OPERAND); }, "Unexpected success calling operator unary* with " #OPERAND); \
61 static_assert(!requires{ (OPERAND) ->* 0; }, "Unexpected success calling operator ->* with " #OPERAND); \
62 /* We need to check the return type to confirm the built-in operator was not selected. */ \
63 static_assert(!requires{ {&(OPERAND)} -> same_as<CORRECT_TYPE>; }, \
64 "Unexpected success calling operator unary& with " #OPERAND); \
65 static_assert(!requires{ {(OPERAND), 0} -> same_as<CORRECT_TYPE>; }, \
66 "Unexpected success calling operator , with " #OPERAND);
68 #define TEST_VALID(OPERAND, CORRECT_TYPE) \
69 static_assert(requires{ (OPERAND) += 0; }, "Unexpected failure calling operator += with " #OPERAND); \
70 static_assert(requires{ (OPERAND) -= 0; }, "Unexpected failure calling operator -= with " #OPERAND); \
71 static_assert(requires{ (OPERAND) *= 0; }, "Unexpected failure calling operator *= with " #OPERAND); \
72 static_assert(requires{ (OPERAND) /= 0; }, "Unexpected failure calling operator /= with " #OPERAND); \
73 static_assert(requires{ (OPERAND) %= 0; }, "Unexpected failure calling operator %= with " #OPERAND); \
74 static_assert(requires{ (OPERAND) &= 0; }, "Unexpected failure calling operator &= with " #OPERAND); \
75 static_assert(requires{ (OPERAND) |= 0; }, "Unexpected failure calling operator |= with " #OPERAND); \
76 static_assert(requires{ (OPERAND) ^= 0; }, "Unexpected failure calling operator ^= with " #OPERAND); \
77 static_assert(requires{ (OPERAND) <<= 0; }, "Unexpected failure calling operator <<= with " #OPERAND); \
78 static_assert(requires{ (OPERAND) >>= 0; }, "Unexpected failure calling operator >>= with " #OPERAND); \
80 static_assert(requires{ ++(OPERAND); }, "Unexpected failure calling operator pre++ with " #OPERAND); \
81 static_assert(requires{ --(OPERAND); }, "Unexpected failure calling operator pre-- with " #OPERAND); \
82 static_assert(requires{ (OPERAND)++; }, "Unexpected failure calling operator post++ with " #OPERAND); \
83 static_assert(requires{ (OPERAND)--; }, "Unexpected failure calling operator post-- with " #OPERAND); \
85 static_assert(requires{ +(OPERAND); }, "Unexpected failure calling operator unary+ with " #OPERAND); \
86 static_assert(requires{ -(OPERAND); }, "Unexpected failure calling operator unary- with " #OPERAND); \
87 static_assert(requires{ (OPERAND) + 0; }, "Unexpected failure calling operator binary+ with " #OPERAND); \
88 static_assert(requires{ (OPERAND) - 0; }, "Unexpected failure calling operator binary- with " #OPERAND); \
89 static_assert(requires{ (OPERAND) * 0; }, "Unexpected failure calling operator binary* with " #OPERAND); \
90 static_assert(requires{ (OPERAND) / 0; }, "Unexpected failure calling operator / with " #OPERAND); \
91 static_assert(requires{ (OPERAND) % 0; }, "Unexpected failure calling operator % with " #OPERAND); \
92 static_assert(requires{ (OPERAND) & 0; }, "Unexpected failure calling operator binary& with " #OPERAND); \
93 static_assert(requires{ (OPERAND) | 0; }, "Unexpected failure calling operator | with " #OPERAND); \
94 static_assert(requires{ (OPERAND) ^ 0; }, "Unexpected failure calling operator ^ with " #OPERAND); \
95 static_assert(requires{ (OPERAND) << 0; }, "Unexpected failure calling operator << with " #OPERAND); \
96 static_assert(requires{ (OPERAND) >> 0; }, "Unexpected failure calling operator >> with " #OPERAND); \
98 static_assert(requires{ !(OPERAND); }, "Unexpected failure calling operator ! with " #OPERAND); \
99 static_assert(requires{ (OPERAND) && 0; }, "Unexpected failure calling operator && with " #OPERAND); \
100 static_assert(requires{ (OPERAND) || 0; }, "Unexpected failure calling operator || with " #OPERAND); \
102 static_assert(requires{ (OPERAND) == 0; }, "Unexpected failure calling operator == with " #OPERAND); \
103 static_assert(requires{ (OPERAND) != 0; }, "Unexpected failure calling operator != with " #OPERAND); \
104 static_assert(requires{ (OPERAND) < 0; }, "Unexpected failure calling operator < with " #OPERAND); \
105 static_assert(requires{ (OPERAND) > 0; }, "Unexpected failure calling operator > with " #OPERAND); \
106 static_assert(requires{ (OPERAND) <= 0; }, "Unexpected failure calling operator <= with " #OPERAND); \
107 static_assert(requires{ (OPERAND) >= 0; }, "Unexpected failure calling operator >= with " #OPERAND); \
108 static_assert(requires{ (OPERAND) <=> 0; }, "Unexpected failure calling operator <=> with " #OPERAND); \
110 static_assert(requires{ *(OPERAND); }, "Unexpected failure calling operator unary* with " #OPERAND); \
111 static_assert(requires{ (OPERAND) ->* 0; }, "Unexpected failure calling operator ->* with " #OPERAND); \
112 /* We need to check the return type to confirm we selected our overload, not the built-in operator. */ \
113 static_assert(requires{ {&(OPERAND)} -> same_as<CORRECT_TYPE>; }, \
114 "Unexpected failure calling operator unary& with " #OPERAND); \
115 static_assert(requires{ {(OPERAND), 0} -> same_as<CORRECT_TYPE>; }, \
116 "Unexpected failure calling operator , with " #OPERAND);
118 // Return types need to be tested for the deduced case
120 #define TEST_VALID_WITH_RETURN_TYPES(OPERAND, CORRECT_TYPE) \
121 static_assert(requires{ {(OPERAND) += 0} -> same_as<CORRECT_TYPE>; }); \
122 static_assert(requires{ {(OPERAND) -= 0} -> same_as<CORRECT_TYPE>; }); \
123 static_assert(requires{ {(OPERAND) *= 0} -> same_as<CORRECT_TYPE>; }); \
124 static_assert(requires{ {(OPERAND) /= 0} -> same_as<CORRECT_TYPE>; }); \
125 static_assert(requires{ {(OPERAND) %= 0} -> same_as<CORRECT_TYPE>; }); \
126 static_assert(requires{ {(OPERAND) &= 0} -> same_as<CORRECT_TYPE>; }); \
127 static_assert(requires{ {(OPERAND) |= 0} -> same_as<CORRECT_TYPE>; }); \
128 static_assert(requires{ {(OPERAND) ^= 0} -> same_as<CORRECT_TYPE>; }); \
129 static_assert(requires{ {(OPERAND) <<= 0} -> same_as<CORRECT_TYPE>; }); \
130 static_assert(requires{ {(OPERAND) >>= 0} -> same_as<CORRECT_TYPE>; }); \
132 static_assert(requires{ {++(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
133 static_assert(requires{ {--(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
134 static_assert(requires{ {(OPERAND)++} -> same_as<CORRECT_TYPE>; }); \
135 static_assert(requires{ {(OPERAND)--} -> same_as<CORRECT_TYPE>; }); \
137 static_assert(requires{ {+(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
138 static_assert(requires{ {-(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
139 static_assert(requires{ {(OPERAND) + 0} -> same_as<CORRECT_TYPE>; }); \
140 static_assert(requires{ {(OPERAND) - 0} -> same_as<CORRECT_TYPE>; }); \
141 static_assert(requires{ {(OPERAND) * 0} -> same_as<CORRECT_TYPE>; }); \
142 static_assert(requires{ {(OPERAND) / 0} -> same_as<CORRECT_TYPE>; }); \
143 static_assert(requires{ {(OPERAND) % 0} -> same_as<CORRECT_TYPE>; }); \
144 static_assert(requires{ {(OPERAND) & 0} -> same_as<CORRECT_TYPE>; }); \
145 static_assert(requires{ {(OPERAND) | 0} -> same_as<CORRECT_TYPE>; }); \
146 static_assert(requires{ {(OPERAND) ^ 0} -> same_as<CORRECT_TYPE>; }); \
147 static_assert(requires{ {(OPERAND) << 0} -> same_as<CORRECT_TYPE>; }); \
148 static_assert(requires{ {(OPERAND) >> 0} -> same_as<CORRECT_TYPE>; }); \
150 static_assert(requires{ {!(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
151 static_assert(requires{ {(OPERAND) && 0} -> same_as<CORRECT_TYPE>; }); \
152 static_assert(requires{ {(OPERAND) || 0} -> same_as<CORRECT_TYPE>; }); \
154 static_assert(requires{ {(OPERAND) == 0} -> same_as<CORRECT_TYPE>; }); \
155 static_assert(requires{ {(OPERAND) != 0} -> same_as<CORRECT_TYPE>; }); \
156 static_assert(requires{ {(OPERAND) < 0} -> same_as<CORRECT_TYPE>; }); \
157 static_assert(requires{ {(OPERAND) > 0} -> same_as<CORRECT_TYPE>; }); \
158 static_assert(requires{ {(OPERAND) <= 0} -> same_as<CORRECT_TYPE>; }); \
159 static_assert(requires{ {(OPERAND) >= 0} -> same_as<CORRECT_TYPE>; }); \
160 static_assert(requires{ {(OPERAND) <=> 0} -> same_as<CORRECT_TYPE>; }); \
162 static_assert(requires{ {*(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
163 static_assert(requires{ {(OPERAND) ->* 0} -> same_as<CORRECT_TYPE>; }); \
164 static_assert(requires{ {&(OPERAND)} -> same_as<CORRECT_TYPE>; }); \
165 static_assert(requires{ {(OPERAND), 0} -> same_as<CORRECT_TYPE>; });
167 template<typename DepValue = Value>
171 TEST_VALID(value, DepValue)
172 TEST_VALID(static_cast<DepValue&&>(value), DepValue)
173 TEST_VALID(static_cast<DepValue const&>(value), DepValue)
174 TEST_VALID(static_cast<DepValue const&&>(value), DepValue)
177 template<typename DepLRef = LRef>
181 TEST_VALID(l_ref, DepLRef&)
182 TEST_INVALID(static_cast<DepLRef&&>(l_ref), DepLRef&)
183 TEST_INVALID(static_cast<DepLRef const&>(l_ref), DepLRef&)
184 TEST_INVALID(static_cast<DepLRef const&&>(l_ref), DepLRef&)
187 template<typename DepRRef = RRef>
191 TEST_INVALID(r_ref, DepRRef&&)
192 TEST_VALID(static_cast<DepRRef&&>(r_ref), DepRRef&&)
193 TEST_INVALID(static_cast<DepRRef const&>(r_ref), DepRRef&&)
194 TEST_INVALID(static_cast<DepRRef const&&>(r_ref), DepRRef&&)
197 template<typename DepConstLRef = ConstLRef>
198 void test_const_l_ref()
200 DepConstLRef const_l_ref{};
201 TEST_VALID(const_l_ref, DepConstLRef const&)
202 TEST_VALID(static_cast<DepConstLRef&&>(const_l_ref), DepConstLRef const&)
203 TEST_VALID(static_cast<DepConstLRef const&>(const_l_ref), DepConstLRef const&)
204 TEST_VALID(static_cast<DepConstLRef const&&>(const_l_ref), DepConstLRef const&)
207 template<typename DepConstRRef = ConstRRef>
208 void test_const_r_ref()
210 DepConstRRef const_r_ref{};
211 TEST_INVALID(const_r_ref, DepConstRRef const&&)
212 TEST_VALID(static_cast<DepConstRRef&&>(const_r_ref), DepConstRRef const&&)
213 TEST_INVALID(static_cast<DepConstRRef const&>(const_r_ref), DepConstRRef const&&)
214 TEST_VALID(static_cast<DepConstRRef const&&>(const_r_ref), DepConstRRef const&&)
217 template<typename DepDeduced = Deduced>
220 DepDeduced deduced{};
222 TEST_VALID_WITH_RETURN_TYPES(deduced, DepDeduced&)
223 TEST_VALID_WITH_RETURN_TYPES(static_cast<DepDeduced&&>(deduced), DepDeduced&&)
224 TEST_VALID_WITH_RETURN_TYPES(static_cast<DepDeduced const&>(deduced), DepDeduced const&)
225 TEST_VALID_WITH_RETURN_TYPES(static_cast<DepDeduced const&&>(deduced), DepDeduced const&&)